qib_iba7220.c revision eddfb675256f49d14e8c5763098afe3eb2c93701
1f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
2f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation.
3f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * All rights reserved.
4f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
5f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
6f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This software is available to you under a choice of one of two
7f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * licenses.  You may choose to be licensed under the terms of the GNU
8f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * General Public License (GPL) Version 2, available from the file
9f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * COPYING in the main directory of this source tree, or the
10f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * OpenIB.org BSD license below:
11f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
12f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *     Redistribution and use in source and binary forms, with or
13f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *     without modification, are permitted provided that the following
14f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *     conditions are met:
15f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
16f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *      - Redistributions of source code must retain the above
17f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        copyright notice, this list of conditions and the following
18f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        disclaimer.
19f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
20f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *      - Redistributions in binary form must reproduce the above
21f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        copyright notice, this list of conditions and the following
22f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        disclaimer in the documentation and/or other materials
23f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        provided with the distribution.
24f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
25f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * SOFTWARE.
33f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
34f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
35f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This file contains all of the code that is specific to the
36f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * QLogic_IB 7220 chip (except that specific to the SerDes)
37f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
38f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
39f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include <linux/interrupt.h>
40f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include <linux/pci.h>
41f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include <linux/delay.h>
42e4dd23d753c3cb0d8533d353069e8b2e8a666360Paul Gortmaker#include <linux/module.h>
43f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include <linux/io.h>
44f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include <rdma/ib_verbs.h>
45f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
46f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include "qib.h"
47f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include "qib_7220.h"
48f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
49f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_setup_7220_setextled(struct qib_pportdata *, u32);
50f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_handle_hwerrors(struct qib_devdata *, char *, size_t);
51f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void sendctrl_7220_mod(struct qib_pportdata *ppd, u32 op);
52f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u32 qib_7220_iblink_state(u64);
53f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u8 qib_7220_phys_portstate(u64);
54f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_sdma_update_7220_tail(struct qib_pportdata *, u16);
55f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_set_ib_7220_lstate(struct qib_pportdata *, u16, u16);
56f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
57f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
58f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This file contains almost all the chip-specific register information and
59f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * access functions for the QLogic QLogic_IB 7220 PCI-Express chip, with the
60f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * exception of SerDes support, which in in qib_sd7220.c.
61f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
62f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
63f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* Below uses machine-generated qib_chipnum_regs.h file */
64f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define KREG_IDX(regname) (QIB_7220_##regname##_OFFS / sizeof(u64))
65f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
66f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* Use defines to tie machine-generated names to lower-case names */
67f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_control KREG_IDX(Control)
68f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_counterregbase KREG_IDX(CntrRegBase)
69f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_errclear KREG_IDX(ErrClear)
70f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_errmask KREG_IDX(ErrMask)
71f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_errstatus KREG_IDX(ErrStatus)
72f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_extctrl KREG_IDX(EXTCtrl)
73f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_extstatus KREG_IDX(EXTStatus)
74f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_gpio_clear KREG_IDX(GPIOClear)
75f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_gpio_mask KREG_IDX(GPIOMask)
76f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_gpio_out KREG_IDX(GPIOOut)
77f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_gpio_status KREG_IDX(GPIOStatus)
78f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_hrtbt_guid KREG_IDX(HRTBT_GUID)
79f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_hwdiagctrl KREG_IDX(HwDiagCtrl)
80f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_hwerrclear KREG_IDX(HwErrClear)
81f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_hwerrmask KREG_IDX(HwErrMask)
82f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_hwerrstatus KREG_IDX(HwErrStatus)
83f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_ibcctrl KREG_IDX(IBCCtrl)
84f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_ibcddrctrl KREG_IDX(IBCDDRCtrl)
85f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_ibcddrstatus KREG_IDX(IBCDDRStatus)
86f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_ibcstatus KREG_IDX(IBCStatus)
87f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_ibserdesctrl KREG_IDX(IBSerDesCtrl)
88f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_intclear KREG_IDX(IntClear)
89f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_intmask KREG_IDX(IntMask)
90f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_intstatus KREG_IDX(IntStatus)
91f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_ncmodectrl KREG_IDX(IBNCModeCtrl)
92f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_palign KREG_IDX(PageAlign)
93f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_partitionkey KREG_IDX(RcvPartitionKey)
94f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_portcnt KREG_IDX(PortCnt)
95f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_rcvbthqp KREG_IDX(RcvBTHQP)
96f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_rcvctrl KREG_IDX(RcvCtrl)
97f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_rcvegrbase KREG_IDX(RcvEgrBase)
98f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_rcvegrcnt KREG_IDX(RcvEgrCnt)
99f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_rcvhdrcnt KREG_IDX(RcvHdrCnt)
100f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_rcvhdrentsize KREG_IDX(RcvHdrEntSize)
101f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_rcvhdrsize KREG_IDX(RcvHdrSize)
102f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_rcvpktledcnt KREG_IDX(RcvPktLEDCnt)
103f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_rcvtidbase KREG_IDX(RcvTIDBase)
104f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_rcvtidcnt KREG_IDX(RcvTIDCnt)
105f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_revision KREG_IDX(Revision)
106f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_scratch KREG_IDX(Scratch)
107f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_sendbuffererror KREG_IDX(SendBufErr0)
108f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_sendctrl KREG_IDX(SendCtrl)
109f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_senddmabase KREG_IDX(SendDmaBase)
110f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_senddmabufmask0 KREG_IDX(SendDmaBufMask0)
111f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_senddmabufmask1 (KREG_IDX(SendDmaBufMask0) + 1)
112f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_senddmabufmask2 (KREG_IDX(SendDmaBufMask0) + 2)
113f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_senddmahead KREG_IDX(SendDmaHead)
114f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_senddmaheadaddr KREG_IDX(SendDmaHeadAddr)
115f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_senddmalengen KREG_IDX(SendDmaLenGen)
116f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_senddmastatus KREG_IDX(SendDmaStatus)
117f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_senddmatail KREG_IDX(SendDmaTail)
118f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_sendpioavailaddr KREG_IDX(SendBufAvailAddr)
119f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_sendpiobufbase KREG_IDX(SendBufBase)
120f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_sendpiobufcnt KREG_IDX(SendBufCnt)
121f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_sendpiosize KREG_IDX(SendBufSize)
122f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_sendregbase KREG_IDX(SendRegBase)
123f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_userregbase KREG_IDX(UserRegBase)
124f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_xgxs_cfg KREG_IDX(XGXSCfg)
125f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
126f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* These must only be written via qib_write_kreg_ctxt() */
127f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_rcvhdraddr KREG_IDX(RcvHdrAddr0)
128f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define kr_rcvhdrtailaddr KREG_IDX(RcvHdrTailAddr0)
129f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
130f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
131f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define CREG_IDX(regname) ((QIB_7220_##regname##_OFFS - \
132f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			QIB_7220_LBIntCnt_OFFS) / sizeof(u64))
133f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
134f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_badformat CREG_IDX(RxVersionErrCnt)
135f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_erricrc CREG_IDX(RxICRCErrCnt)
136f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_errlink CREG_IDX(RxLinkMalformCnt)
137f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_errlpcrc CREG_IDX(RxLPCRCErrCnt)
138f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_errpkey CREG_IDX(RxPKeyMismatchCnt)
139f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_rcvflowctrl_err CREG_IDX(RxFlowCtrlViolCnt)
140f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_err_rlen CREG_IDX(RxLenErrCnt)
141f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_errslen CREG_IDX(TxLenErrCnt)
142f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_errtidfull CREG_IDX(RxTIDFullErrCnt)
143f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_errtidvalid CREG_IDX(RxTIDValidErrCnt)
144f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_errvcrc CREG_IDX(RxVCRCErrCnt)
145f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_ibstatuschange CREG_IDX(IBStatusChangeCnt)
146f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_lbint CREG_IDX(LBIntCnt)
147f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_invalidrlen CREG_IDX(RxMaxMinLenErrCnt)
148f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_invalidslen CREG_IDX(TxMaxMinLenErrCnt)
149f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_lbflowstall CREG_IDX(LBFlowStallCnt)
150f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_pktrcv CREG_IDX(RxDataPktCnt)
151f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_pktrcvflowctrl CREG_IDX(RxFlowPktCnt)
152f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_pktsend CREG_IDX(TxDataPktCnt)
153f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_pktsendflow CREG_IDX(TxFlowPktCnt)
154f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_portovfl CREG_IDX(RxP0HdrEgrOvflCnt)
155f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_rcvebp CREG_IDX(RxEBPCnt)
156f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_rcvovfl CREG_IDX(RxBufOvflCnt)
157f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_senddropped CREG_IDX(TxDroppedPktCnt)
158f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_sendstall CREG_IDX(TxFlowStallCnt)
159f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_sendunderrun CREG_IDX(TxUnderrunCnt)
160f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_wordrcv CREG_IDX(RxDwordCnt)
161f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_wordsend CREG_IDX(TxDwordCnt)
162f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_txunsupvl CREG_IDX(TxUnsupVLErrCnt)
163f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_rxdroppkt CREG_IDX(RxDroppedPktCnt)
164f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_iblinkerrrecov CREG_IDX(IBLinkErrRecoveryCnt)
165f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_iblinkdown CREG_IDX(IBLinkDownedCnt)
166f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_ibsymbolerr CREG_IDX(IBSymbolErrCnt)
167f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_vl15droppedpkt CREG_IDX(RxVL15DroppedPktCnt)
168f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_rxotherlocalphyerr CREG_IDX(RxOtherLocalPhyErrCnt)
169f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_excessbufferovfl CREG_IDX(ExcessBufferOvflCnt)
170f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_locallinkintegrityerr CREG_IDX(LocalLinkIntegrityErrCnt)
171f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_rxvlerr CREG_IDX(RxVlErrCnt)
172f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_rxdlidfltr CREG_IDX(RxDlidFltrCnt)
173f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_psstat CREG_IDX(PSStat)
174f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_psstart CREG_IDX(PSStart)
175f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_psinterval CREG_IDX(PSInterval)
176f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_psrcvdatacount CREG_IDX(PSRcvDataCount)
177f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_psrcvpktscount CREG_IDX(PSRcvPktsCount)
178f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_psxmitdatacount CREG_IDX(PSXmitDataCount)
179f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_psxmitpktscount CREG_IDX(PSXmitPktsCount)
180f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_psxmitwaitcount CREG_IDX(PSXmitWaitCount)
181f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_txsdmadesc CREG_IDX(TxSDmaDescCnt)
182f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define cr_pcieretrydiag CREG_IDX(PcieRetryBufDiagQwordCnt)
183f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
184f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define SYM_RMASK(regname, fldname) ((u64)              \
185f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIB_7220_##regname##_##fldname##_RMASK)
186f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define SYM_MASK(regname, fldname) ((u64)               \
187f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIB_7220_##regname##_##fldname##_RMASK <<       \
188f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 QIB_7220_##regname##_##fldname##_LSB)
189f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define SYM_LSB(regname, fldname) (QIB_7220_##regname##_##fldname##_LSB)
190f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define SYM_FIELD(value, regname, fldname) ((u64) \
191f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	(((value) >> SYM_LSB(regname, fldname)) & \
192f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 SYM_RMASK(regname, fldname)))
193f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define ERR_MASK(fldname) SYM_MASK(ErrMask, fldname##Mask)
194f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define HWE_MASK(fldname) SYM_MASK(HwErrMask, fldname##Mask)
195f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
196f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* ibcctrl bits */
197f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_IBCC_LINKINITCMD_DISABLE 1
198f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* cycle through TS1/TS2 till OK */
199f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_IBCC_LINKINITCMD_POLL 2
200f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* wait for TS1, then go on */
201f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_IBCC_LINKINITCMD_SLEEP 3
202f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_IBCC_LINKINITCMD_SHIFT 16
203f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
204f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_IBCC_LINKCMD_DOWN 1           /* move to 0x11 */
205f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_IBCC_LINKCMD_ARMED 2          /* move to 0x21 */
206f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_IBCC_LINKCMD_ACTIVE 3 /* move to 0x31 */
207f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
208f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define BLOB_7220_IBCHG 0x81
209f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
210f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
211f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * We could have a single register get/put routine, that takes a group type,
212f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * but this is somewhat clearer and cleaner.  It also gives us some error
213f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * checking.  64 bit register reads should always work, but are inefficient
214f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * on opteron (the northbridge always generates 2 separate HT 32 bit reads),
215f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * so we use kreg32 wherever possible.  User register and counter register
216f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * reads are always 32 bit reads, so only one form of those routines.
217f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
218f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
219f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
220f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_read_ureg32 - read 32-bit virtualized per-context register
221f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dd: device
222f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @regno: register number
223f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @ctxt: context number
224f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
225f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Return the contents of a register that is virtualized to be per context.
226f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Returns -1 on errors (not distinguishable from valid contents at
227f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * runtime; we may add a separate error variable at some point).
228f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
229f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic inline u32 qib_read_ureg32(const struct qib_devdata *dd,
230f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				  enum qib_ureg regno, int ctxt)
231f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
232f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!dd->kregbase || !(dd->flags & QIB_PRESENT))
233f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		return 0;
234f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
235f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->userbase)
236f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		return readl(regno + (u64 __iomem *)
237f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			     ((char __iomem *)dd->userbase +
238f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			      dd->ureg_align * ctxt));
239f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
240f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		return readl(regno + (u64 __iomem *)
241f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			     (dd->uregbase +
242f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			      (char __iomem *)dd->kregbase +
243f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			      dd->ureg_align * ctxt));
244f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
245f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
246f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
247f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_write_ureg - write 32-bit virtualized per-context register
248f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dd: device
249f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @regno: register number
250f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @value: value
251f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @ctxt: context
252f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
253f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Write the contents of a register that is virtualized to be per context.
254f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
255f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic inline void qib_write_ureg(const struct qib_devdata *dd,
256f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				  enum qib_ureg regno, u64 value, int ctxt)
257f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
258f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 __iomem *ubase;
259f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
260f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->userbase)
261f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ubase = (u64 __iomem *)
262f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			((char __iomem *) dd->userbase +
263f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 dd->ureg_align * ctxt);
264f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
265f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ubase = (u64 __iomem *)
266f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			(dd->uregbase +
267f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 (char __iomem *) dd->kregbase +
268f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 dd->ureg_align * ctxt);
269f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
270f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->kregbase && (dd->flags & QIB_PRESENT))
271f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		writeq(value, &ubase[regno]);
272f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
273f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
274f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
275f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_write_kreg_ctxt - write a device's per-ctxt 64-bit kernel register
276f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dd: the qlogic_ib device
277f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @regno: the register number to write
278f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @ctxt: the context containing the register
279f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @value: the value to write
280f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
281f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic inline void qib_write_kreg_ctxt(const struct qib_devdata *dd,
282f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				       const u16 regno, unsigned ctxt,
283f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				       u64 value)
284f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
285f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, regno + ctxt, value);
286f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
287f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
288f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic inline void write_7220_creg(const struct qib_devdata *dd,
289f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				   u16 regno, u64 value)
290f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
291f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->cspec->cregbase && (dd->flags & QIB_PRESENT))
292f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		writeq(value, &dd->cspec->cregbase[regno]);
293f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
294f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
295f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic inline u64 read_7220_creg(const struct qib_devdata *dd, u16 regno)
296f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
297f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!dd->cspec->cregbase || !(dd->flags & QIB_PRESENT))
298f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		return 0;
299f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return readq(&dd->cspec->cregbase[regno]);
300f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
301f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
302f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic inline u32 read_7220_creg32(const struct qib_devdata *dd, u16 regno)
303f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
304f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!dd->cspec->cregbase || !(dd->flags & QIB_PRESENT))
305f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		return 0;
306f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return readl(&dd->cspec->cregbase[regno]);
307f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
308f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
309f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* kr_revision bits */
310f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_R_EMULATORREV_MASK ((1ULL << 22) - 1)
311f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_R_EMULATORREV_SHIFT 40
312f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
313f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* kr_control bits */
314f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_C_RESET (1U << 7)
315f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
316f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* kr_intstatus, kr_intclear, kr_intmask bits */
317f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_I_RCVURG_MASK ((1ULL << 17) - 1)
318f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_I_RCVURG_SHIFT 32
319f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_I_RCVAVAIL_MASK ((1ULL << 17) - 1)
320f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_I_RCVAVAIL_SHIFT 0
321f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_I_SERDESTRIMDONE (1ULL << 27)
322f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
323f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_C_FREEZEMODE 0x00000002
324f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_C_LINKENABLE 0x00000004
325f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
326f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_I_SDMAINT             0x8000000000000000ULL
327f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_I_SDMADISABLED        0x4000000000000000ULL
328f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_I_ERROR               0x0000000080000000ULL
329f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_I_SPIOSENT            0x0000000040000000ULL
330f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_I_SPIOBUFAVAIL        0x0000000020000000ULL
331f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_I_GPIO                0x0000000010000000ULL
332f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
333f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* variables for sanity checking interrupt and errors */
334f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_I_BITSEXTANT \
335f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		(QLOGIC_IB_I_SDMAINT | QLOGIC_IB_I_SDMADISABLED | \
336f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		(QLOGIC_IB_I_RCVURG_MASK << QLOGIC_IB_I_RCVURG_SHIFT) | \
337f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		(QLOGIC_IB_I_RCVAVAIL_MASK << \
338f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 QLOGIC_IB_I_RCVAVAIL_SHIFT) | \
339f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_I_ERROR | QLOGIC_IB_I_SPIOSENT | \
340f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_I_SPIOBUFAVAIL | QLOGIC_IB_I_GPIO | \
341f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_I_SERDESTRIMDONE)
342f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
343f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_HWE_BITSEXTANT \
344f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	       (HWE_MASK(RXEMemParityErr) | \
345f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		HWE_MASK(TXEMemParityErr) | \
346f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		(QLOGIC_IB_HWE_PCIEMEMPARITYERR_MASK <<	 \
347f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 QLOGIC_IB_HWE_PCIEMEMPARITYERR_SHIFT) | \
348f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIE1PLLFAILED | \
349f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIE0PLLFAILED | \
350f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIEPOISONEDTLP | \
351f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIECPLTIMEOUT | \
352f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIEBUSPARITYXTLH | \
353f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIEBUSPARITYXADM | \
354f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIEBUSPARITYRADM | \
355f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		HWE_MASK(PowerOnBISTFailed) |	  \
356f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_COREPLL_FBSLIP | \
357f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_COREPLL_RFSLIP | \
358f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_SERDESPLLFAILED | \
359f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		HWE_MASK(IBCBusToSPCParityErr) | \
360f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		HWE_MASK(IBCBusFromSPCParityErr) | \
361f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIECPLDATAQUEUEERR | \
362f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIECPLHDRQUEUEERR | \
363f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_SDMAMEMREADERR | \
364f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_CLK_UC_PLLNOTLOCKED | \
365f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIESERDESQ0PCLKNOTDETECT | \
366f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIESERDESQ1PCLKNOTDETECT | \
367f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIESERDESQ2PCLKNOTDETECT | \
368f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIESERDESQ3PCLKNOTDETECT | \
369f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_DDSRXEQMEMORYPARITYERR | \
370f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_IB_UC_MEMORYPARITYERR | \
371f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIE_UC_OCT0MEMORYPARITYERR | \
372f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_HWE_PCIE_UC_OCT1MEMORYPARITYERR)
373f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
374f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_E_BITSEXTANT							\
375f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	(ERR_MASK(RcvFormatErr) | ERR_MASK(RcvVCRCErr) |		\
376f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvICRCErr) | ERR_MASK(RcvMinPktLenErr) |		\
377f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvMaxPktLenErr) | ERR_MASK(RcvLongPktLenErr) |	\
378f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvShortPktLenErr) | ERR_MASK(RcvUnexpectedCharErr) | \
379f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvUnsupportedVLErr) | ERR_MASK(RcvEBPErr) |		\
380f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvIBFlowErr) | ERR_MASK(RcvBadVersionErr) |		\
381f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvEgrFullErr) | ERR_MASK(RcvHdrFullErr) |		\
382f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvBadTidErr) | ERR_MASK(RcvHdrLenErr) |		\
383f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvHdrErr) | ERR_MASK(RcvIBLostLinkErr) |		\
384f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SendSpecialTriggerErr) |				\
385f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SDmaDisabledErr) | ERR_MASK(SendMinPktLenErr) |	\
386f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SendMaxPktLenErr) | ERR_MASK(SendUnderRunErr) |	\
387f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SendPktLenErr) | ERR_MASK(SendDroppedSmpPktErr) |	\
388f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SendDroppedDataPktErr) |				\
389f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SendPioArmLaunchErr) |				\
390f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SendUnexpectedPktNumErr) |				\
391f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SendUnsupportedVLErr) | ERR_MASK(SendBufMisuseErr) |	\
392f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SDmaGenMismatchErr) | ERR_MASK(SDmaOutOfBoundErr) |	\
393f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SDmaTailOutOfBoundErr) | ERR_MASK(SDmaBaseErr) |	\
394f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SDma1stDescErr) | ERR_MASK(SDmaRpyTagErr) |		\
395f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SDmaDwEnErr) | ERR_MASK(SDmaMissingDwErr) |		\
396f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SDmaUnexpDataErr) |					\
397f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(IBStatusChanged) | ERR_MASK(InvalidAddrErr) |		\
398f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(ResetNegated) | ERR_MASK(HardwareErr) |		\
399f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SDmaDescAddrMisalignErr) |				\
400f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(InvalidEEPCmd))
401f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
402f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
403f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIEMEMPARITYERR_MASK  0x00000000000000ffULL
404f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIEMEMPARITYERR_SHIFT 0
405f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIEPOISONEDTLP      0x0000000010000000ULL
406f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIECPLTIMEOUT       0x0000000020000000ULL
407f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIEBUSPARITYXTLH    0x0000000040000000ULL
408f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIEBUSPARITYXADM    0x0000000080000000ULL
409f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIEBUSPARITYRADM    0x0000000100000000ULL
410f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_COREPLL_FBSLIP       0x0080000000000000ULL
411f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_COREPLL_RFSLIP       0x0100000000000000ULL
412f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIE1PLLFAILED       0x0400000000000000ULL
413f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIE0PLLFAILED       0x0800000000000000ULL
414f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_SERDESPLLFAILED      0x1000000000000000ULL
415f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* specific to this chip */
416f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIECPLDATAQUEUEERR         0x0000000000000040ULL
417f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIECPLHDRQUEUEERR          0x0000000000000080ULL
418f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_SDMAMEMREADERR              0x0000000010000000ULL
419f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_CLK_UC_PLLNOTLOCKED          0x2000000000000000ULL
420f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIESERDESQ0PCLKNOTDETECT   0x0100000000000000ULL
421f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIESERDESQ1PCLKNOTDETECT   0x0200000000000000ULL
422f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIESERDESQ2PCLKNOTDETECT   0x0400000000000000ULL
423f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIESERDESQ3PCLKNOTDETECT   0x0800000000000000ULL
424f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_DDSRXEQMEMORYPARITYERR       0x0000008000000000ULL
425f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_IB_UC_MEMORYPARITYERR        0x0000004000000000ULL
426f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIE_UC_OCT0MEMORYPARITYERR 0x0000001000000000ULL
427f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_HWE_PCIE_UC_OCT1MEMORYPARITYERR 0x0000002000000000ULL
428f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
429f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBCC_LINKCMD_SHIFT 19
430f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
431f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* kr_ibcddrctrl bits */
432f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_DLIDLMC_MASK        0xFFFFFFFFUL
433f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_DLIDLMC_SHIFT       32
434f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
435f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_HRTBT_MASK  (SYM_RMASK(IBCDDRCtrl, HRTBT_AUTO) | \
436f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				 SYM_RMASK(IBCDDRCtrl, HRTBT_ENB))
437f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_HRTBT_SHIFT SYM_LSB(IBCDDRCtrl, HRTBT_ENB)
438f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
439f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_LANE_REV_SUPPORTED (1<<8)
440f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_LREV_MASK   1
441f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_LREV_SHIFT  8
442f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_RXPOL_MASK  1
443f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_RXPOL_SHIFT 7
444f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_WIDTH_SHIFT 5
445f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_WIDTH_MASK  0x3
446f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_WIDTH_1X_ONLY       (0 << IBA7220_IBC_WIDTH_SHIFT)
447f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_WIDTH_4X_ONLY       (1 << IBA7220_IBC_WIDTH_SHIFT)
448f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_WIDTH_AUTONEG       (2 << IBA7220_IBC_WIDTH_SHIFT)
449f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_SPEED_AUTONEG       (1 << 1)
450f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_SPEED_SDR           (1 << 2)
451f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_SPEED_DDR           (1 << 3)
452f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_SPEED_AUTONEG_MASK  (0x7 << 1)
453f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_IBC_IBTA_1_2_MASK       (1)
454f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
455f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* kr_ibcddrstatus */
456f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* link latency shift is 0, don't bother defining */
457f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_DDRSTAT_LINKLAT_MASK    0x3ffffff
458f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
459f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* kr_extstatus bits */
460f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_EXTS_FREQSEL 0x2
461f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_EXTS_SERDESSEL 0x4
462f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_EXTS_MEMBIST_ENDTEST     0x0000000000004000
463f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_EXTS_MEMBIST_DISABLED    0x0000000000008000
464f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
465f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* kr_xgxsconfig bits */
466f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_XGXS_RESET          0x5ULL
467f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_XGXS_FC_SAFE        (1ULL << 63)
468f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
469f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* kr_rcvpktledcnt */
470f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_LEDBLINK_ON_SHIFT 32 /* 4ns period on after packet */
471f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_LEDBLINK_OFF_SHIFT 0 /* 4ns period off before next on */
472f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
473f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define _QIB_GPIO_SDA_NUM 1
474f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define _QIB_GPIO_SCL_NUM 0
475f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QIB_TWSI_EEPROM_DEV 0xA2 /* All Production 7220 cards. */
476f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QIB_TWSI_TEMP_DEV 0x98
477f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
478f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* HW counter clock is at 4nsec */
479f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QIB_7220_PSXMITWAIT_CHECK_RATE 4000
480f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
481f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_R_INTRAVAIL_SHIFT 17
482f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_R_PKEY_DIS_SHIFT 34
483f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_R_TAILUPD_SHIFT 35
484f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_R_CTXTCFG_SHIFT 36
485f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
486f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_HDRHEAD_PKTINT_SHIFT 32 /* interrupt cnt in upper 32 bits */
487f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
488f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
489f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * the size bits give us 2^N, in KB units.  0 marks as invalid,
490f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * and 7 is reserved.  We currently use only 2KB and 4KB
491f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
492f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_TID_SZ_SHIFT 37 /* shift to 3bit size selector */
493f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_TID_SZ_2K (1UL << IBA7220_TID_SZ_SHIFT) /* 2KB */
494f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_TID_SZ_4K (2UL << IBA7220_TID_SZ_SHIFT) /* 4KB */
495f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_TID_PA_SHIFT 11U /* TID addr in chip stored w/o low bits */
496f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define PBC_7220_VL15_SEND (1ULL << 63) /* pbc; VL15, no credit check */
497f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define PBC_7220_VL15_SEND_CTRL (1ULL << 31) /* control version of same */
498f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
499f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define AUTONEG_TRIES 5 /* sequential retries to negotiate DDR */
500f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
501f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* packet rate matching delay multiplier */
502f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u8 rate_to_delay[2][2] = {
503f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* 1x, 4x */
504f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	{   8, 2 }, /* SDR */
505f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	{   4, 1 }  /* DDR */
506f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell};
507f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
508f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u8 ib_rate_to_delay[IB_RATE_120_GBPS + 1] = {
509f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_RATE_2_5_GBPS] = 8,
510f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_RATE_5_GBPS] = 4,
511f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_RATE_10_GBPS] = 2,
512f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_RATE_20_GBPS] = 1
513f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell};
514f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
515f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_LINKSPEED_SHIFT SYM_LSB(IBCStatus, LinkSpeedActive)
516f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBA7220_LINKWIDTH_SHIFT SYM_LSB(IBCStatus, LinkWidthActive)
517f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
518f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* link training states, from IBC */
519f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_LT_STATE_DISABLED        0x00
520f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_LT_STATE_LINKUP          0x01
521f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_LT_STATE_POLLACTIVE      0x02
522f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_LT_STATE_POLLQUIET       0x03
523f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_LT_STATE_SLEEPDELAY      0x04
524f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_LT_STATE_SLEEPQUIET      0x05
525f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_LT_STATE_CFGDEBOUNCE     0x08
526f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_LT_STATE_CFGRCVFCFG      0x09
527f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_LT_STATE_CFGWAITRMT      0x0a
528f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_LT_STATE_CFGIDLE 0x0b
529f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_LT_STATE_RECOVERRETRAIN  0x0c
530f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_LT_STATE_RECOVERWAITRMT  0x0e
531f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_LT_STATE_RECOVERIDLE     0x0f
532f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
533f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* link state machine states from IBC */
534f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_L_STATE_DOWN             0x0
535f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_L_STATE_INIT             0x1
536f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_L_STATE_ARM              0x2
537f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_L_STATE_ACTIVE           0x3
538f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IB_7220_L_STATE_ACT_DEFER        0x4
539f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
540f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic const u8 qib_7220_physportstate[0x20] = {
541f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_7220_LT_STATE_DISABLED] = IB_PHYSPORTSTATE_DISABLED,
542f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_7220_LT_STATE_LINKUP] = IB_PHYSPORTSTATE_LINKUP,
543f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_7220_LT_STATE_POLLACTIVE] = IB_PHYSPORTSTATE_POLL,
544f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_7220_LT_STATE_POLLQUIET] = IB_PHYSPORTSTATE_POLL,
545f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_7220_LT_STATE_SLEEPDELAY] = IB_PHYSPORTSTATE_SLEEP,
546f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_7220_LT_STATE_SLEEPQUIET] = IB_PHYSPORTSTATE_SLEEP,
547f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_7220_LT_STATE_CFGDEBOUNCE] =
548f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		IB_PHYSPORTSTATE_CFG_TRAIN,
549f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_7220_LT_STATE_CFGRCVFCFG] =
550f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		IB_PHYSPORTSTATE_CFG_TRAIN,
551f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_7220_LT_STATE_CFGWAITRMT] =
552f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		IB_PHYSPORTSTATE_CFG_TRAIN,
553f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_7220_LT_STATE_CFGIDLE] = IB_PHYSPORTSTATE_CFG_TRAIN,
554f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_7220_LT_STATE_RECOVERRETRAIN] =
555f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		IB_PHYSPORTSTATE_LINK_ERR_RECOVER,
556f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_7220_LT_STATE_RECOVERWAITRMT] =
557f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		IB_PHYSPORTSTATE_LINK_ERR_RECOVER,
558f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[IB_7220_LT_STATE_RECOVERIDLE] =
559f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		IB_PHYSPORTSTATE_LINK_ERR_RECOVER,
560f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[0x10] = IB_PHYSPORTSTATE_CFG_TRAIN,
561f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[0x11] = IB_PHYSPORTSTATE_CFG_TRAIN,
562f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[0x12] = IB_PHYSPORTSTATE_CFG_TRAIN,
563f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[0x13] = IB_PHYSPORTSTATE_CFG_TRAIN,
564f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[0x14] = IB_PHYSPORTSTATE_CFG_TRAIN,
565f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[0x15] = IB_PHYSPORTSTATE_CFG_TRAIN,
566f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[0x16] = IB_PHYSPORTSTATE_CFG_TRAIN,
567f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[0x17] = IB_PHYSPORTSTATE_CFG_TRAIN
568f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell};
569f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
570f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellint qib_special_trigger;
571f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellmodule_param_named(special_trigger, qib_special_trigger, int, S_IRUGO);
572f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph CampbellMODULE_PARM_DESC(special_trigger, "Enable SpecialTrigger arm/launch");
573f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
574f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBCBUSFRSPCPARITYERR HWE_MASK(IBCBusFromSPCParityErr)
575f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define IBCBUSTOSPCPARITYERR HWE_MASK(IBCBusToSPCParityErr)
576f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
577f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define SYM_MASK_BIT(regname, fldname, bit) ((u64) \
578f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	(1ULL << (SYM_LSB(regname, fldname) + (bit))))
579f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
580f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define TXEMEMPARITYERR_PIOBUF \
581f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	SYM_MASK_BIT(HwErrMask, TXEMemParityErrMask, 0)
582f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define TXEMEMPARITYERR_PIOPBC \
583f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	SYM_MASK_BIT(HwErrMask, TXEMemParityErrMask, 1)
584f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define TXEMEMPARITYERR_PIOLAUNCHFIFO \
585f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	SYM_MASK_BIT(HwErrMask, TXEMemParityErrMask, 2)
586f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
587f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define RXEMEMPARITYERR_RCVBUF \
588f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	SYM_MASK_BIT(HwErrMask, RXEMemParityErrMask, 0)
589f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define RXEMEMPARITYERR_LOOKUPQ \
590f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	SYM_MASK_BIT(HwErrMask, RXEMemParityErrMask, 1)
591f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define RXEMEMPARITYERR_EXPTID \
592f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	SYM_MASK_BIT(HwErrMask, RXEMemParityErrMask, 2)
593f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define RXEMEMPARITYERR_EAGERTID \
594f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	SYM_MASK_BIT(HwErrMask, RXEMemParityErrMask, 3)
595f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define RXEMEMPARITYERR_FLAGBUF \
596f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	SYM_MASK_BIT(HwErrMask, RXEMemParityErrMask, 4)
597f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define RXEMEMPARITYERR_DATAINFO \
598f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	SYM_MASK_BIT(HwErrMask, RXEMemParityErrMask, 5)
599f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define RXEMEMPARITYERR_HDRINFO \
600f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	SYM_MASK_BIT(HwErrMask, RXEMemParityErrMask, 6)
601f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
602f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* 7220 specific hardware errors... */
603f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic const struct qib_hwerror_msgs qib_7220_hwerror_msgs[] = {
604f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* generic hardware errors */
605f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(IBCBUSFRSPCPARITYERR, "QIB2IB Parity"),
606f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(IBCBUSTOSPCPARITYERR, "IB2QIB Parity"),
607f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
608f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(TXEMEMPARITYERR_PIOBUF,
609f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "TXE PIOBUF Memory Parity"),
610f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(TXEMEMPARITYERR_PIOPBC,
611f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "TXE PIOPBC Memory Parity"),
612f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(TXEMEMPARITYERR_PIOLAUNCHFIFO,
613f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "TXE PIOLAUNCHFIFO Memory Parity"),
614f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
615f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(RXEMEMPARITYERR_RCVBUF,
616f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "RXE RCVBUF Memory Parity"),
617f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(RXEMEMPARITYERR_LOOKUPQ,
618f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "RXE LOOKUPQ Memory Parity"),
619f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(RXEMEMPARITYERR_EAGERTID,
620f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "RXE EAGERTID Memory Parity"),
621f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(RXEMEMPARITYERR_EXPTID,
622f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "RXE EXPTID Memory Parity"),
623f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(RXEMEMPARITYERR_FLAGBUF,
624f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "RXE FLAGBUF Memory Parity"),
625f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(RXEMEMPARITYERR_DATAINFO,
626f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "RXE DATAINFO Memory Parity"),
627f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(RXEMEMPARITYERR_HDRINFO,
628f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "RXE HDRINFO Memory Parity"),
629f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
630f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* chip-specific hardware errors */
631f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIEPOISONEDTLP,
632f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIe Poisoned TLP"),
633f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIECPLTIMEOUT,
634f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIe completion timeout"),
635f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
636f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * In practice, it's unlikely wthat we'll see PCIe PLL, or bus
637f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * parity or memory parity error failures, because most likely we
638f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * won't be able to talk to the core of the chip.  Nonetheless, we
639f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * might see them, if they are in parts of the PCIe core that aren't
640f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * essential.
641f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
642f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIE1PLLFAILED,
643f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIePLL1"),
644f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIE0PLLFAILED,
645f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIePLL0"),
646f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIEBUSPARITYXTLH,
647f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIe XTLH core parity"),
648f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIEBUSPARITYXADM,
649f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIe ADM TX core parity"),
650f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIEBUSPARITYRADM,
651f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIe ADM RX core parity"),
652f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_SERDESPLLFAILED,
653f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "SerDes PLL"),
654f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIECPLDATAQUEUEERR,
655f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIe cpl header queue"),
656f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIECPLHDRQUEUEERR,
657f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIe cpl data queue"),
658f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_SDMAMEMREADERR,
659f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "Send DMA memory read"),
660f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_CLK_UC_PLLNOTLOCKED,
661f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "uC PLL clock not locked"),
662f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIESERDESQ0PCLKNOTDETECT,
663f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIe serdes Q0 no clock"),
664f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIESERDESQ1PCLKNOTDETECT,
665f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIe serdes Q1 no clock"),
666f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIESERDESQ2PCLKNOTDETECT,
667f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIe serdes Q2 no clock"),
668f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIESERDESQ3PCLKNOTDETECT,
669f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIe serdes Q3 no clock"),
670f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_DDSRXEQMEMORYPARITYERR,
671f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "DDS RXEQ memory parity"),
672f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_IB_UC_MEMORYPARITYERR,
673f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "IB uC memory parity"),
674f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIE_UC_OCT0MEMORYPARITYERR,
675f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIe uC oct0 memory parity"),
676f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QLOGIC_IB_HWE_MSG(QLOGIC_IB_HWE_PCIE_UC_OCT1MEMORYPARITYERR,
677f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  "PCIe uC oct1 memory parity"),
678f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell};
679f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
680f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define RXE_PARITY (RXEMEMPARITYERR_EAGERTID|RXEMEMPARITYERR_EXPTID)
681f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
682f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_E_PKTERRS (\
683f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SendPktLenErr) |				\
684f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SendDroppedDataPktErr) |			\
685f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(RcvVCRCErr) |					\
686f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(RcvICRCErr) |					\
687f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(RcvShortPktLenErr) |				\
688f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(RcvEBPErr))
689f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
690f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* Convenience for decoding Send DMA errors */
691f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define QLOGIC_IB_E_SDMAERRS ( \
692f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaGenMismatchErr) |				\
693f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaOutOfBoundErr) |				\
694f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaTailOutOfBoundErr) | ERR_MASK(SDmaBaseErr) | \
695f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDma1stDescErr) | ERR_MASK(SDmaRpyTagErr) |	\
696f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaDwEnErr) | ERR_MASK(SDmaMissingDwErr) |	\
697f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaUnexpDataErr) |				\
698f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaDescAddrMisalignErr) |			\
699f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaDisabledErr) |				\
700f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SendBufMisuseErr))
701f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
702f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* These are all rcv-related errors which we want to count for stats */
703f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define E_SUM_PKTERRS \
704f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	(ERR_MASK(RcvHdrLenErr) | ERR_MASK(RcvBadTidErr) |		\
705f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvBadVersionErr) | ERR_MASK(RcvHdrErr) |		\
706f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvLongPktLenErr) | ERR_MASK(RcvShortPktLenErr) |	\
707f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvMaxPktLenErr) | ERR_MASK(RcvMinPktLenErr) |	\
708f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvFormatErr) | ERR_MASK(RcvUnsupportedVLErr) |	\
709f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvUnexpectedCharErr) | ERR_MASK(RcvEBPErr))
710f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
711f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* These are all send-related errors which we want to count for stats */
712f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define E_SUM_ERRS \
713f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	(ERR_MASK(SendPioArmLaunchErr) | ERR_MASK(SendUnexpectedPktNumErr) | \
714f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SendDroppedDataPktErr) | ERR_MASK(SendDroppedSmpPktErr) | \
715f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SendMaxPktLenErr) | ERR_MASK(SendUnsupportedVLErr) |	\
716f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SendMinPktLenErr) | ERR_MASK(SendPktLenErr) |		\
717f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(InvalidAddrErr))
718f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
719f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
720f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * this is similar to E_SUM_ERRS, but can't ignore armlaunch, don't ignore
721f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * errors not related to freeze and cancelling buffers.  Can't ignore
722f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * armlaunch because could get more while still cleaning up, and need
723f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * to cancel those as they happen.
724f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
725f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define E_SPKT_ERRS_IGNORE \
726f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	(ERR_MASK(SendDroppedDataPktErr) | ERR_MASK(SendDroppedSmpPktErr) | \
727f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SendMaxPktLenErr) | ERR_MASK(SendMinPktLenErr) |	\
728f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SendPktLenErr))
729f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
730f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
731f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * these are errors that can occur when the link changes state while
732f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * a packet is being sent or received.  This doesn't cover things
733f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * like EBP or VCRC that can be the result of a sending having the
734f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * link change state, so we receive a "known bad" packet.
735f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
736f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define E_SUM_LINK_PKTERRS \
737f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	(ERR_MASK(SendDroppedDataPktErr) | ERR_MASK(SendDroppedSmpPktErr) | \
738f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(SendMinPktLenErr) | ERR_MASK(SendPktLenErr) |		\
739f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvShortPktLenErr) | ERR_MASK(RcvMinPktLenErr) |	\
740f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 ERR_MASK(RcvUnexpectedCharErr))
741f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
742f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void autoneg_7220_work(struct work_struct *);
743f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u32 __iomem *qib_7220_getsendbuf(struct qib_pportdata *, u64, u32 *);
744f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
745f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
746f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Called when we might have an error that is specific to a particular
747f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * PIO buffer, and may need to cancel that buffer, so it can be re-used.
748f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * because we don't need to force the update of pioavail.
749f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
750f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_disarm_7220_senderrbufs(struct qib_pportdata *ppd)
751f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
752f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long sbuf[3];
753f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
754f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
755f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
756f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * It's possible that sendbuffererror could have bits set; might
757f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * have already done this as a result of hardware error handling.
758f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
759f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* read these before writing errorclear */
760f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	sbuf[0] = qib_read_kreg64(dd, kr_sendbuffererror);
761f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	sbuf[1] = qib_read_kreg64(dd, kr_sendbuffererror + 1);
762f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	sbuf[2] = qib_read_kreg64(dd, kr_sendbuffererror + 2);
763f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
764f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (sbuf[0] || sbuf[1] || sbuf[2])
765f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_disarm_piobufs_set(dd, sbuf,
766f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				       dd->piobcnt2k + dd->piobcnt4k);
767f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
768f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
769f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_txe_recover(struct qib_devdata *dd)
770f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
771f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_devinfo(dd->pcidev, "Recovering from TXE PIO parity error\n");
772f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_disarm_7220_senderrbufs(dd->pport);
773f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
774f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
775f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
776f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This is called with interrupts disabled and sdma_lock held.
777f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
778f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_sdma_sendctrl(struct qib_pportdata *ppd, unsigned op)
779f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
780f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
781f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 set_sendctrl = 0;
782f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 clr_sendctrl = 0;
783f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
784f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_SDMA_SENDCTRL_OP_ENABLE)
785f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		set_sendctrl |= SYM_MASK(SendCtrl, SDmaEnable);
786f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
787f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		clr_sendctrl |= SYM_MASK(SendCtrl, SDmaEnable);
788f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
789f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_SDMA_SENDCTRL_OP_INTENABLE)
790f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		set_sendctrl |= SYM_MASK(SendCtrl, SDmaIntEnable);
791f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
792f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		clr_sendctrl |= SYM_MASK(SendCtrl, SDmaIntEnable);
793f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
794f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_SDMA_SENDCTRL_OP_HALT)
795f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		set_sendctrl |= SYM_MASK(SendCtrl, SDmaHalt);
796f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
797f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		clr_sendctrl |= SYM_MASK(SendCtrl, SDmaHalt);
798f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
799f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock(&dd->sendctrl_lock);
800f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
801f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->sendctrl |= set_sendctrl;
802f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->sendctrl &= ~clr_sendctrl;
803f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
804f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_sendctrl, dd->sendctrl);
805f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_scratch, 0);
806f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
807f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock(&dd->sendctrl_lock);
808f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
809f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
810f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_decode_7220_sdma_errs(struct qib_pportdata *ppd,
811f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				      u64 err, char *buf, size_t blen)
812f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
813f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	static const struct {
814f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u64 err;
815f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		const char *msg;
816f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} errs[] = {
817f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		{ ERR_MASK(SDmaGenMismatchErr),
818f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		  "SDmaGenMismatch" },
819f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		{ ERR_MASK(SDmaOutOfBoundErr),
820f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		  "SDmaOutOfBound" },
821f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		{ ERR_MASK(SDmaTailOutOfBoundErr),
822f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		  "SDmaTailOutOfBound" },
823f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		{ ERR_MASK(SDmaBaseErr),
824f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		  "SDmaBase" },
825f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		{ ERR_MASK(SDma1stDescErr),
826f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		  "SDma1stDesc" },
827f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		{ ERR_MASK(SDmaRpyTagErr),
828f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		  "SDmaRpyTag" },
829f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		{ ERR_MASK(SDmaDwEnErr),
830f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		  "SDmaDwEn" },
831f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		{ ERR_MASK(SDmaMissingDwErr),
832f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		  "SDmaMissingDw" },
833f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		{ ERR_MASK(SDmaUnexpDataErr),
834f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		  "SDmaUnexpData" },
835f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		{ ERR_MASK(SDmaDescAddrMisalignErr),
836f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		  "SDmaDescAddrMisalign" },
837f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		{ ERR_MASK(SendBufMisuseErr),
838f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		  "SendBufMisuse" },
839f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		{ ERR_MASK(SDmaDisabledErr),
840f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		  "SDmaDisabled" },
841f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	};
842f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int i;
843f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	size_t bidx = 0;
844f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
845f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (i = 0; i < ARRAY_SIZE(errs); i++) {
846f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (err & errs[i].err)
847f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			bidx += scnprintf(buf + bidx, blen - bidx,
848f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					 "%s ", errs[i].msg);
849f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
850f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
851f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
852f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
853f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This is called as part of link down clean up so disarm and flush
854f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * all send buffers so that SMP packets can be sent.
855f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
856f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_sdma_hw_clean_up(struct qib_pportdata *ppd)
857f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
858f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* This will trigger the Abort interrupt */
859f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	sendctrl_7220_mod(ppd, QIB_SENDCTRL_DISARM_ALL | QIB_SENDCTRL_FLUSH |
860f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  QIB_SENDCTRL_AVAIL_BLIP);
861f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->dd->upd_pio_shadow  = 1; /* update our idea of what's busy */
862f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
863f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
864f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_sdma_7220_setlengen(struct qib_pportdata *ppd)
865f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
866f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
867f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Set SendDmaLenGen and clear and set
868f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * the MSB of the generation count to enable generation checking
869f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * and load the internal generation counter.
870f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
871f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(ppd->dd, kr_senddmalengen, ppd->sdma_descq_cnt);
872f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(ppd->dd, kr_senddmalengen,
873f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		       ppd->sdma_descq_cnt |
874f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		       (1ULL << QIB_7220_SendDmaLenGen_Generation_MSB));
875f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
876f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
877f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_sdma_hw_start_up(struct qib_pportdata *ppd)
878f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
879f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_sdma_7220_setlengen(ppd);
880f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_sdma_update_7220_tail(ppd, 0); /* Set SendDmaTail */
881f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->sdma_head_dma[0] = 0;
882f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
883f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
884f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define DISABLES_SDMA (							\
885f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaDisabledErr) |				\
886f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaBaseErr) |					\
887f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaTailOutOfBoundErr) |			\
888f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaOutOfBoundErr) |				\
889f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDma1stDescErr) |				\
890f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaRpyTagErr) |				\
891f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaGenMismatchErr) |				\
892f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaDescAddrMisalignErr) |			\
893f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaMissingDwErr) |				\
894f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(SDmaDwEnErr))
895f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
896f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void sdma_7220_errors(struct qib_pportdata *ppd, u64 errs)
897f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
898f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
899f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
900f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	char *msg;
901f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
902f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	errs &= QLOGIC_IB_E_SDMAERRS;
903f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
904f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	msg = dd->cspec->sdmamsgbuf;
905f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_decode_7220_sdma_errs(ppd, errs, msg, sizeof dd->cspec->sdmamsgbuf);
906f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&ppd->sdma_lock, flags);
907f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
908f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (errs & ERR_MASK(SendBufMisuseErr)) {
909f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		unsigned long sbuf[3];
910f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
911f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sbuf[0] = qib_read_kreg64(dd, kr_sendbuffererror);
912f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sbuf[1] = qib_read_kreg64(dd, kr_sendbuffererror + 1);
913f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sbuf[2] = qib_read_kreg64(dd, kr_sendbuffererror + 2);
914f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
915f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(ppd->dd,
916f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    "IB%u:%u SendBufMisuse: %04lx %016lx %016lx\n",
917f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    ppd->dd->unit, ppd->port, sbuf[2], sbuf[1],
918f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    sbuf[0]);
919f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
920f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
921f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (errs & ERR_MASK(SDmaUnexpDataErr))
922f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "IB%u:%u SDmaUnexpData\n", ppd->dd->unit,
923f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    ppd->port);
924f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
925f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	switch (ppd->sdma_state.current_state) {
926f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s00_hw_down:
927f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* not expecting any interrupts */
928f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
929f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
930f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s10_hw_start_up_wait:
931f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* handled in intr path */
932f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
933f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
934f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s20_idle:
935f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* not expecting any interrupts */
936f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
937f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
938f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s30_sw_clean_up_wait:
939f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* not expecting any interrupts */
940f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
941f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
942f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s40_hw_clean_up_wait:
943f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (errs & ERR_MASK(SDmaDisabledErr))
944f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			__qib_sdma_process_event(ppd,
945f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qib_sdma_event_e50_hw_cleaned);
946f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
947f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
948f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s50_hw_halt_wait:
949f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* handled in intr path */
950f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
951f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
952f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s99_running:
953f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (errs & DISABLES_SDMA)
954f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			__qib_sdma_process_event(ppd,
955f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qib_sdma_event_e7220_err_halted);
956f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
957f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
958f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
959f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&ppd->sdma_lock, flags);
960f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
961f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
962f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
963f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Decode the error status into strings, deciding whether to always
964f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * print * it or not depending on "normal packet errors" vs everything
965f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * else.   Return 1 if "real" errors, otherwise 0 if only packet
966f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * errors, so caller can decide what to print with the string.
967f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
968f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_decode_7220_err(struct qib_devdata *dd, char *buf, size_t blen,
969f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			       u64 err)
970f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
971f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int iserr = 1;
972f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
973f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	*buf = '\0';
974f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & QLOGIC_IB_E_PKTERRS) {
975f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!(err & ~QLOGIC_IB_E_PKTERRS))
976f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			iserr = 0;
977f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if ((err & ERR_MASK(RcvICRCErr)) &&
978f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    !(err & (ERR_MASK(RcvVCRCErr) | ERR_MASK(RcvEBPErr))))
979f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			strlcat(buf, "CRC ", blen);
980f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!iserr)
981f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto done;
982f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
983f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvHdrLenErr))
984f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "rhdrlen ", blen);
985f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvBadTidErr))
986f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "rbadtid ", blen);
987f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvBadVersionErr))
988f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "rbadversion ", blen);
989f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvHdrErr))
990f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "rhdr ", blen);
991f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(SendSpecialTriggerErr))
992f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "sendspecialtrigger ", blen);
993f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvLongPktLenErr))
994f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "rlongpktlen ", blen);
995f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvMaxPktLenErr))
996f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "rmaxpktlen ", blen);
997f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvMinPktLenErr))
998f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "rminpktlen ", blen);
999f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(SendMinPktLenErr))
1000f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "sminpktlen ", blen);
1001f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvFormatErr))
1002f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "rformaterr ", blen);
1003f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvUnsupportedVLErr))
1004f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "runsupvl ", blen);
1005f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvUnexpectedCharErr))
1006f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "runexpchar ", blen);
1007f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvIBFlowErr))
1008f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "ribflow ", blen);
1009f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(SendUnderRunErr))
1010f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "sunderrun ", blen);
1011f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(SendPioArmLaunchErr))
1012f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "spioarmlaunch ", blen);
1013f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(SendUnexpectedPktNumErr))
1014f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "sunexperrpktnum ", blen);
1015f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(SendDroppedSmpPktErr))
1016f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "sdroppedsmppkt ", blen);
1017f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(SendMaxPktLenErr))
1018f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "smaxpktlen ", blen);
1019f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(SendUnsupportedVLErr))
1020f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "sunsupVL ", blen);
1021f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(InvalidAddrErr))
1022f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "invalidaddr ", blen);
1023f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvEgrFullErr))
1024f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "rcvegrfull ", blen);
1025f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvHdrFullErr))
1026f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "rcvhdrfull ", blen);
1027f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(IBStatusChanged))
1028f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "ibcstatuschg ", blen);
1029f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(RcvIBLostLinkErr))
1030f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "riblostlink ", blen);
1031f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(HardwareErr))
1032f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "hardware ", blen);
1033f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(ResetNegated))
1034f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "reset ", blen);
1035f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & QLOGIC_IB_E_SDMAERRS)
1036f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_decode_7220_sdma_errs(dd->pport, err, buf, blen);
1037f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (err & ERR_MASK(InvalidEEPCmd))
1038f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(buf, "invalideepromcmd ", blen);
1039f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbelldone:
1040f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return iserr;
1041f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1042f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1043f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void reenable_7220_chase(unsigned long opaque)
1044f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1045f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_pportdata *ppd = (struct qib_pportdata *)opaque;
1046f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->cpspec->chase_timer.expires = 0;
1047f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_set_ib_7220_lstate(ppd, QLOGIC_IB_IBCC_LINKCMD_DOWN,
1048f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_IBCC_LINKINITCMD_POLL);
1049f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1050f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1051f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void handle_7220_chase(struct qib_pportdata *ppd, u64 ibcst)
1052f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1053f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u8 ibclt;
10548482d5d1bc18c17429a89ad37f8b74d5a16de239Mike Marciniszyn	unsigned long tnow;
1055f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1056f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ibclt = (u8)SYM_FIELD(ibcst, IBCStatus, LinkTrainingState);
1057f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1058f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
1059f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Detect and handle the state chase issue, where we can
1060f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * get stuck if we are unlucky on timing on both sides of
1061f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * the link.   If we are, we disable, set a timer, and
1062f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * then re-enable.
1063f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
1064f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	switch (ibclt) {
1065f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_7220_LT_STATE_CFGRCVFCFG:
1066f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_7220_LT_STATE_CFGWAITRMT:
1067f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_7220_LT_STATE_TXREVLANES:
1068f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_7220_LT_STATE_CFGENH:
10698482d5d1bc18c17429a89ad37f8b74d5a16de239Mike Marciniszyn		tnow = jiffies;
1070f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ppd->cpspec->chase_end &&
10718482d5d1bc18c17429a89ad37f8b74d5a16de239Mike Marciniszyn		    time_after(tnow, ppd->cpspec->chase_end)) {
1072f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->chase_end = 0;
1073f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_set_ib_7220_lstate(ppd,
1074f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				QLOGIC_IB_IBCC_LINKCMD_DOWN,
1075f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
1076f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->chase_timer.expires = jiffies +
1077f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				QIB_CHASE_DIS_TIME;
1078f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			add_timer(&ppd->cpspec->chase_timer);
1079f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else if (!ppd->cpspec->chase_end)
1080f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->chase_end = tnow + QIB_CHASE_TIME;
1081f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
1082f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1083f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	default:
1084f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->chase_end = 0;
1085f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
1086f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1087f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1088f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1089f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void handle_7220_errors(struct qib_devdata *dd, u64 errs)
1090f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1091f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	char *msg;
1092f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 ignore_this_time = 0;
1093f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 iserr = 0;
1094f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int log_idx;
1095f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_pportdata *ppd = dd->pport;
1096f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 mask;
1097f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1098f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* don't report errors that are masked */
1099f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	errs &= dd->cspec->errormask;
1100f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	msg = dd->cspec->emsgbuf;
1101f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1102f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* do these first, they are most important */
1103f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (errs & ERR_MASK(HardwareErr))
1104f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_7220_handle_hwerrors(dd, msg, sizeof dd->cspec->emsgbuf);
1105f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
1106f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		for (log_idx = 0; log_idx < QIB_EEP_LOG_CNT; ++log_idx)
1107f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (errs & dd->eep_st_masks[log_idx].errs_to_log)
1108f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qib_inc_eeprom_err(dd, log_idx, 1);
1109f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1110f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (errs & QLOGIC_IB_E_SDMAERRS)
1111f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sdma_7220_errors(ppd, errs);
1112f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1113f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (errs & ~IB_E_BITSEXTANT)
1114f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "error interrupt with unknown errors "
1115f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    "%llx set\n", (unsigned long long)
1116f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    (errs & ~IB_E_BITSEXTANT));
1117f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1118f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (errs & E_SUM_ERRS) {
1119f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_disarm_7220_senderrbufs(ppd);
1120f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if ((errs & E_SUM_LINK_PKTERRS) &&
1121f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    !(ppd->lflags & QIBL_LINKACTIVE)) {
1122f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/*
1123f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * This can happen when trying to bring the link
1124f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * up, but the IB link changes state at the "wrong"
1125f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * time. The IB logic then complains that the packet
1126f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * isn't valid.  We don't want to confuse people, so
1127f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * we just don't print them, except at debug
1128f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 */
1129f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ignore_this_time = errs & E_SUM_LINK_PKTERRS;
1130f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1131f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else if ((errs & E_SUM_LINK_PKTERRS) &&
1132f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		   !(ppd->lflags & QIBL_LINKACTIVE)) {
1133f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
1134f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * This can happen when SMA is trying to bring the link
1135f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * up, but the IB link changes state at the "wrong" time.
1136f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * The IB logic then complains that the packet isn't
1137f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * valid.  We don't want to confuse people, so we just
1138f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * don't print them, except at debug
1139f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
1140f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ignore_this_time = errs & E_SUM_LINK_PKTERRS;
1141f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1142f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1143f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_errclear, errs);
1144f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1145f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	errs &= ~ignore_this_time;
1146f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!errs)
1147f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
1148f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1149f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
1150f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * The ones we mask off are handled specially below
1151f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * or above.  Also mask SDMADISABLED by default as it
1152f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * is too chatty.
1153f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
1154f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	mask = ERR_MASK(IBStatusChanged) |
1155f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(RcvEgrFullErr) | ERR_MASK(RcvHdrFullErr) |
1156f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ERR_MASK(HardwareErr) | ERR_MASK(SDmaDisabledErr);
1157f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1158f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_decode_7220_err(dd, msg, sizeof dd->cspec->emsgbuf, errs & ~mask);
1159f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1160f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (errs & E_SUM_PKTERRS)
1161f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_stats.sps_rcverrs++;
1162f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (errs & E_SUM_ERRS)
1163f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_stats.sps_txerrs++;
1164f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	iserr = errs & ~(E_SUM_PKTERRS | QLOGIC_IB_E_PKTERRS |
1165f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 ERR_MASK(SDmaDisabledErr));
1166f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1167f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (errs & ERR_MASK(IBStatusChanged)) {
1168f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u64 ibcs;
1169f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1170f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ibcs = qib_read_kreg64(dd, kr_ibcstatus);
1171f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG))
1172f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			handle_7220_chase(ppd, ibcs);
1173f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1174f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* Update our picture of width and speed from chip */
1175f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->link_width_active =
1176f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			((ibcs >> IBA7220_LINKWIDTH_SHIFT) & 1) ?
1177f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    IB_WIDTH_4X : IB_WIDTH_1X;
1178f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->link_speed_active =
1179f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			((ibcs >> IBA7220_LINKSPEED_SHIFT) & 1) ?
1180f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    QIB_IB_DDR : QIB_IB_SDR;
1181f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1182f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
1183f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Since going into a recovery state causes the link state
1184f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * to go down and since recovery is transitory, it is better
1185f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * if we "miss" ever seeing the link training state go into
1186f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * recovery (i.e., ignore this transition for link state
1187f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * special handling purposes) without updating lastibcstat.
1188f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
1189f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qib_7220_phys_portstate(ibcs) !=
1190f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					    IB_PHYSPORTSTATE_LINK_ERR_RECOVER)
1191f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_handle_e_ibstatuschanged(ppd, ibcs);
1192f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1193f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1194f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (errs & ERR_MASK(ResetNegated)) {
1195f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "Got reset, requires re-init "
1196f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    "(unload and reload driver)\n");
1197f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->flags &= ~QIB_INITTED;  /* needs re-init */
1198f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* mark as having had error */
1199f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		*dd->devstatusp |= QIB_STATUS_HWERROR;
1200f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		*dd->pport->statusp &= ~QIB_STATUS_IB_CONF;
1201f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1202f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1203f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (*msg && iserr)
1204f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_porterr(dd, ppd->port, "%s error\n", msg);
1205f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1206f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ppd->state_wanted & ppd->lflags)
1207f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		wake_up_interruptible(&ppd->state_wait);
1208f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1209f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
1210f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * If there were hdrq or egrfull errors, wake up any processes
1211f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * waiting in poll.  We used to try to check which contexts had
1212f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * the overflow, but given the cost of that and the chip reads
1213f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * to support it, it's better to just wake everybody up if we
1214f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * get an overflow; waiters can poll again if it's not them.
1215f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
1216f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (errs & (ERR_MASK(RcvEgrFullErr) | ERR_MASK(RcvHdrFullErr))) {
1217f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_handle_urcv(dd, ~0U);
1218f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (errs & ERR_MASK(RcvEgrFullErr))
1219f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_stats.sps_buffull++;
1220f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		else
1221f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_stats.sps_hdrfull++;
1222f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1223f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbelldone:
1224f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return;
1225f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1226f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1227f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* enable/disable chip from delivering interrupts */
1228f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_set_intr_state(struct qib_devdata *dd, u32 enable)
1229f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1230f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (enable) {
1231f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (dd->flags & QIB_BADINTR)
1232f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			return;
1233f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_intmask, ~0ULL);
1234f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* force re-interrupt of any pending interrupts. */
1235f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_intclear, 0ULL);
1236f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else
1237f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_intmask, 0ULL);
1238f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1239f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1240f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
1241f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Try to cleanup as much as possible for anything that might have gone
1242f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * wrong while in freeze mode, such as pio buffers being written by user
1243f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * processes (causing armlaunch), send errors due to going into freeze mode,
1244f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * etc., and try to avoid causing extra interrupts while doing so.
1245f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Forcibly update the in-memory pioavail register copies after cleanup
1246f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * because the chip won't do it while in freeze mode (the register values
1247f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * themselves are kept correct).
1248f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Make sure that we don't lose any important interrupts by using the chip
1249f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * feature that says that writing 0 to a bit in *clear that is set in
1250f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * *status will cause an interrupt to be generated again (if allowed by
1251f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * the *mask value).
1252f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This is in chip-specific code because of all of the register accesses,
1253f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * even though the details are similar on most chips.
1254f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1255f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_clear_freeze(struct qib_devdata *dd)
1256f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1257f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* disable error interrupts, to avoid confusion */
1258f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_errmask, 0ULL);
1259f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1260f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* also disable interrupts; errormask is sometimes overwriten */
1261f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_7220_set_intr_state(dd, 0);
1262f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1263f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_cancel_sends(dd->pport);
1264f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1265f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* clear the freeze, and be sure chip saw it */
1266f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_control, dd->control);
1267f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_read_kreg32(dd, kr_scratch);
1268f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1269f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* force in-memory update now we are out of freeze */
1270f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_force_pio_avail_update(dd);
1271f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1272f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
1273f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * force new interrupt if any hwerr, error or interrupt bits are
1274f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * still set, and clear "safe" send packet errors related to freeze
1275f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * and cancelling sends.  Re-enable error interrupts before possible
1276f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * force of re-interrupt on pending interrupts.
1277f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
1278f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_hwerrclear, 0ULL);
1279f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_errclear, E_SPKT_ERRS_IGNORE);
1280f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_errmask, dd->cspec->errormask);
1281f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_7220_set_intr_state(dd, 1);
1282f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1283f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1284f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
1285f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_7220_handle_hwerrors - display hardware errors.
1286f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dd: the qlogic_ib device
1287f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @msg: the output buffer
1288f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @msgl: the size of the output buffer
1289f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
1290f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Use same msg buffer as regular errors to avoid excessive stack
1291f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * use.  Most hardware errors are catastrophic, but for right now,
1292f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * we'll print them and continue.  We reuse the same message buffer as
1293f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * handle_7220_errors() to avoid excessive stack usage.
1294f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1295f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_handle_hwerrors(struct qib_devdata *dd, char *msg,
1296f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				     size_t msgl)
1297f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1298f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 hwerrs;
1299f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 bits, ctrl;
1300f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int isfatal = 0;
1301f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	char *bitsmsg;
1302f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int log_idx;
1303f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1304f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	hwerrs = qib_read_kreg64(dd, kr_hwerrstatus);
1305f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!hwerrs)
1306f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
1307f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (hwerrs == ~0ULL) {
1308f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "Read of hardware error status failed "
1309f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    "(all bits set); ignoring\n");
1310f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
1311f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1312f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_stats.sps_hwerrs++;
1313f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1314f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
1315f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Always clear the error status register, except MEMBISTFAIL,
1316f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * regardless of whether we continue or stop using the chip.
1317f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * We want that set so we know it failed, even across driver reload.
1318f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * We'll still ignore it in the hwerrmask.  We do this partly for
1319f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * diagnostics, but also for support.
1320f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
1321f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_hwerrclear,
1322f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		       hwerrs & ~HWE_MASK(PowerOnBISTFailed));
1323f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1324f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	hwerrs &= dd->cspec->hwerrmask;
1325f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1326f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* We log some errors to EEPROM, check if we have any of those. */
1327f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (log_idx = 0; log_idx < QIB_EEP_LOG_CNT; ++log_idx)
1328f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (hwerrs & dd->eep_st_masks[log_idx].hwerrs_to_log)
1329f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_inc_eeprom_err(dd, log_idx, 1);
1330f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (hwerrs & ~(TXEMEMPARITYERR_PIOBUF | TXEMEMPARITYERR_PIOPBC |
1331f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		       RXE_PARITY))
1332f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_devinfo(dd->pcidev, "Hardware error: hwerr=0x%llx "
1333f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 "(cleared)\n", (unsigned long long) hwerrs);
1334f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1335f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (hwerrs & ~IB_HWE_BITSEXTANT)
1336f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "hwerror interrupt with unknown errors "
1337f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    "%llx set\n", (unsigned long long)
1338f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    (hwerrs & ~IB_HWE_BITSEXTANT));
1339f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1340f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (hwerrs & QLOGIC_IB_HWE_IB_UC_MEMORYPARITYERR)
1341f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_sd7220_clr_ibpar(dd);
1342f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1343f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ctrl = qib_read_kreg32(dd, kr_control);
1344f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if ((ctrl & QLOGIC_IB_C_FREEZEMODE) && !dd->diag_client) {
1345f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
1346f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Parity errors in send memory are recoverable by h/w
1347f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * just do housekeeping, exit freeze mode and continue.
1348f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
1349f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (hwerrs & (TXEMEMPARITYERR_PIOBUF |
1350f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			      TXEMEMPARITYERR_PIOPBC)) {
1351f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_7220_txe_recover(dd);
1352f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			hwerrs &= ~(TXEMEMPARITYERR_PIOBUF |
1353f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				    TXEMEMPARITYERR_PIOPBC);
1354f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1355f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (hwerrs)
1356f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			isfatal = 1;
1357f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		else
1358f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_7220_clear_freeze(dd);
1359f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1360f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1361f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	*msg = '\0';
1362f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1363f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (hwerrs & HWE_MASK(PowerOnBISTFailed)) {
1364f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		isfatal = 1;
1365f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(msg, "[Memory BIST test failed, "
1366f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			"InfiniPath hardware unusable]", msgl);
1367f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* ignore from now on, so disable until driver reloaded */
1368f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->hwerrmask &= ~HWE_MASK(PowerOnBISTFailed);
1369f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_hwerrmask, dd->cspec->hwerrmask);
1370f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1371f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1372f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_format_hwerrors(hwerrs, qib_7220_hwerror_msgs,
1373f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    ARRAY_SIZE(qib_7220_hwerror_msgs), msg, msgl);
1374f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1375f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	bitsmsg = dd->cspec->bitsmsgbuf;
1376f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (hwerrs & (QLOGIC_IB_HWE_PCIEMEMPARITYERR_MASK <<
1377f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		      QLOGIC_IB_HWE_PCIEMEMPARITYERR_SHIFT)) {
1378f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		bits = (u32) ((hwerrs >>
1379f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			       QLOGIC_IB_HWE_PCIEMEMPARITYERR_SHIFT) &
1380f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			      QLOGIC_IB_HWE_PCIEMEMPARITYERR_MASK);
1381f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		snprintf(bitsmsg, sizeof dd->cspec->bitsmsgbuf,
1382f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 "[PCIe Mem Parity Errs %x] ", bits);
1383f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(msg, bitsmsg, msgl);
1384f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1385f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1386f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define _QIB_PLL_FAIL (QLOGIC_IB_HWE_COREPLL_FBSLIP |   \
1387f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 QLOGIC_IB_HWE_COREPLL_RFSLIP)
1388f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1389f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (hwerrs & _QIB_PLL_FAIL) {
1390f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		isfatal = 1;
1391f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		snprintf(bitsmsg, sizeof dd->cspec->bitsmsgbuf,
1392f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 "[PLL failed (%llx), InfiniPath hardware unusable]",
1393f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 (unsigned long long) hwerrs & _QIB_PLL_FAIL);
1394f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		strlcat(msg, bitsmsg, msgl);
1395f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* ignore from now on, so disable until driver reloaded */
1396f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->hwerrmask &= ~(hwerrs & _QIB_PLL_FAIL);
1397f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_hwerrmask, dd->cspec->hwerrmask);
1398f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1399f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1400f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (hwerrs & QLOGIC_IB_HWE_SERDESPLLFAILED) {
1401f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
1402f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * If it occurs, it is left masked since the eternal
1403f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * interface is unused.
1404f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
1405f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->hwerrmask &= ~QLOGIC_IB_HWE_SERDESPLLFAILED;
1406f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_hwerrmask, dd->cspec->hwerrmask);
1407f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1408f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1409f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_dev_err(dd, "%s hardware error\n", msg);
1410f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1411f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (isfatal && !dd->diag_client) {
1412f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "Fatal Hardware Error, no longer"
1413f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    " usable, SN %.16s\n", dd->serial);
1414f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
1415f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * For /sys status file and user programs to print; if no
1416f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * trailing brace is copied, we'll know it was truncated.
1417f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
1418f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (dd->freezemsg)
1419f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			snprintf(dd->freezemsg, dd->freezelen,
1420f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				 "{%s}", msg);
1421f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_disable_after_error(dd);
1422f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1423f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail:;
1424f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1425f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1426f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
1427f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_7220_init_hwerrors - enable hardware errors
1428f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dd: the qlogic_ib device
1429f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
1430f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * now that we have finished initializing everything that might reasonably
1431f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * cause a hardware error, and cleared those errors bits as they occur,
1432f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * we can enable hardware errors in the mask (potentially enabling
1433f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * freeze mode), and enable hardware errors as errors (along with
1434f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * everything else) in errormask
1435f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1436f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_init_hwerrors(struct qib_devdata *dd)
1437f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1438f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 val;
1439f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 extsval;
1440f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1441f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	extsval = qib_read_kreg64(dd, kr_extstatus);
1442f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1443f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!(extsval & (QLOGIC_IB_EXTS_MEMBIST_ENDTEST |
1444f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 QLOGIC_IB_EXTS_MEMBIST_DISABLED)))
1445f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "MemBIST did not complete!\n");
1446f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (extsval & QLOGIC_IB_EXTS_MEMBIST_DISABLED)
1447f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_devinfo(dd->pcidev, "MemBIST is disabled.\n");
1448f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1449f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	val = ~0ULL;    /* default to all hwerrors become interrupts, */
1450f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1451f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	val &= ~QLOGIC_IB_HWE_IB_UC_MEMORYPARITYERR;
1452f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->hwerrmask = val;
1453f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1454f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_hwerrclear, ~HWE_MASK(PowerOnBISTFailed));
1455f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_hwerrmask, dd->cspec->hwerrmask);
1456f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1457f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* clear all */
1458f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_errclear, ~0ULL);
1459f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* enable errors that are masked, at least this first time. */
1460f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_errmask, ~0ULL);
1461f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->errormask = qib_read_kreg64(dd, kr_errmask);
1462f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* clear any interrupts up to this point (ints still not enabled) */
1463f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_intclear, ~0ULL);
1464f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1465f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1466f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
1467f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Disable and enable the armlaunch error.  Used for PIO bandwidth testing
1468f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * on chips that are count-based, rather than trigger-based.  There is no
1469f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * reference counting, but that's also fine, given the intended use.
1470f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Only chip-specific because it's all register accesses
1471f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1472f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_set_7220_armlaunch(struct qib_devdata *dd, u32 enable)
1473f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1474f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (enable) {
1475f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_errclear, ERR_MASK(SendPioArmLaunchErr));
1476f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->errormask |= ERR_MASK(SendPioArmLaunchErr);
1477f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else
1478f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->errormask &= ~ERR_MASK(SendPioArmLaunchErr);
1479f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_errmask, dd->cspec->errormask);
1480f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1481f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1482f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
1483f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Formerly took parameter <which> in pre-shifted,
1484f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * pre-merged form with LinkCmd and LinkInitCmd
1485f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * together, and assuming the zero was NOP.
1486f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1487f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_set_ib_7220_lstate(struct qib_pportdata *ppd, u16 linkcmd,
1488f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				   u16 linitcmd)
1489f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1490f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 mod_wd;
1491f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
1492f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
1493f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1494f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (linitcmd == QLOGIC_IB_IBCC_LINKINITCMD_DISABLE) {
1495f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
1496f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * If we are told to disable, note that so link-recovery
1497f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * code does not attempt to bring us back up.
1498f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
1499f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock_irqsave(&ppd->lflags_lock, flags);
1500f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->lflags |= QIBL_IB_LINK_DISABLED;
1501f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
1502f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else if (linitcmd || linkcmd == QLOGIC_IB_IBCC_LINKCMD_DOWN) {
1503f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
1504f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Any other linkinitcmd will lead to LINKDOWN and then
1505f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * to INIT (if all is well), so clear flag to let
1506f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * link-recovery code attempt to bring us back up.
1507f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
1508f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock_irqsave(&ppd->lflags_lock, flags);
1509f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->lflags &= ~QIBL_IB_LINK_DISABLED;
1510f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
1511f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1512f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1513f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	mod_wd = (linkcmd << IBA7220_IBCC_LINKCMD_SHIFT) |
1514f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		(linitcmd << QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
1515f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1516f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_ibcctrl, ppd->cpspec->ibcctrl | mod_wd);
1517f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* write to chip to prevent back-to-back writes of ibc reg */
1518f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_scratch, 0);
1519f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1520f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1521f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
1522f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * All detailed interaction with the SerDes has been moved to qib_sd7220.c
1523f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
1524f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * The portion of IBA7220-specific bringup_serdes() that actually deals with
1525f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * registers and memory within the SerDes itself is qib_sd7220_init().
1526f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1527f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1528f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
1529f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_7220_bringup_serdes - bring up the serdes
1530f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @ppd: physical port on the qlogic_ib device
1531f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1532f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_7220_bringup_serdes(struct qib_pportdata *ppd)
1533f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1534f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
1535f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 val, prev_val, guid, ibc;
1536f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int ret = 0;
1537f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1538f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* Put IBC in reset, sends disabled */
1539f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->control &= ~QLOGIC_IB_C_LINKENABLE;
1540f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_control, 0ULL);
1541f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1542f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qib_compat_ddr_negotiate) {
1543f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibdeltainprog = 1;
1544f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibsymsnap = read_7220_creg32(dd, cr_ibsymbolerr);
1545f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->iblnkerrsnap =
1546f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			read_7220_creg32(dd, cr_iblinkerrrecov);
1547f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1548f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1549f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* flowcontrolwatermark is in units of KBytes */
1550f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ibc = 0x5ULL << SYM_LSB(IBCCtrl, FlowCtrlWaterMark);
1551f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
1552f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * How often flowctrl sent.  More or less in usecs; balance against
1553f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * watermark value, so that in theory senders always get a flow
1554f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * control update in time to not let the IB link go idle.
1555f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
1556f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ibc |= 0x3ULL << SYM_LSB(IBCCtrl, FlowCtrlPeriod);
1557f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* max error tolerance */
1558f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ibc |= 0xfULL << SYM_LSB(IBCCtrl, PhyerrThreshold);
1559f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* use "real" buffer space for */
1560f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ibc |= 4ULL << SYM_LSB(IBCCtrl, CreditScale);
1561f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* IB credit flow control. */
1562f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ibc |= 0xfULL << SYM_LSB(IBCCtrl, OverrunThreshold);
1563f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
1564f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * set initial max size pkt IBC will send, including ICRC; it's the
1565f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * PIO buffer size in dwords, less 1; also see qib_set_mtu()
1566f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
1567f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ibc |= ((u64)(ppd->ibmaxlen >> 2) + 1) << SYM_LSB(IBCCtrl, MaxPktLen);
1568f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->cpspec->ibcctrl = ibc; /* without linkcmd or linkinitcmd! */
1569f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1570f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* initially come up waiting for TS1, without sending anything. */
1571f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	val = ppd->cpspec->ibcctrl | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
1572f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
1573f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_ibcctrl, val);
1574f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1575f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!ppd->cpspec->ibcddrctrl) {
1576f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* not on re-init after reset */
1577f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibcddrctrl = qib_read_kreg64(dd, kr_ibcddrctrl);
1578f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1579f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ppd->link_speed_enabled == (QIB_IB_SDR | QIB_IB_DDR))
1580f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->ibcddrctrl |=
1581f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				IBA7220_IBC_SPEED_AUTONEG_MASK |
1582f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				IBA7220_IBC_IBTA_1_2_MASK;
1583f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		else
1584f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->ibcddrctrl |=
1585f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->link_speed_enabled == QIB_IB_DDR ?
1586f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				IBA7220_IBC_SPEED_DDR : IBA7220_IBC_SPEED_SDR;
1587f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if ((ppd->link_width_enabled & (IB_WIDTH_1X | IB_WIDTH_4X)) ==
1588f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    (IB_WIDTH_1X | IB_WIDTH_4X))
1589f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->ibcddrctrl |= IBA7220_IBC_WIDTH_AUTONEG;
1590f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		else
1591f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->ibcddrctrl |=
1592f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->link_width_enabled == IB_WIDTH_4X ?
1593f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				IBA7220_IBC_WIDTH_4X_ONLY :
1594f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				IBA7220_IBC_WIDTH_1X_ONLY;
1595f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1596f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* always enable these on driver reload, not sticky */
1597f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibcddrctrl |=
1598f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			IBA7220_IBC_RXPOL_MASK << IBA7220_IBC_RXPOL_SHIFT;
1599f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibcddrctrl |=
1600f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			IBA7220_IBC_HRTBT_MASK << IBA7220_IBC_HRTBT_SHIFT;
1601f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1602f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* enable automatic lane reversal detection for receive */
1603f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibcddrctrl |= IBA7220_IBC_LANE_REV_SUPPORTED;
1604f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else
1605f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* write to chip to prevent back-to-back writes of ibc reg */
1606f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_scratch, 0);
1607f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1608f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_ibcddrctrl, ppd->cpspec->ibcddrctrl);
1609f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_scratch, 0);
1610f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1611f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_ncmodectrl, 0Ull);
1612f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_scratch, 0);
1613f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1614f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = qib_sd7220_init(dd);
1615f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1616f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	val = qib_read_kreg64(dd, kr_xgxs_cfg);
1617f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	prev_val = val;
1618f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	val |= QLOGIC_IB_XGXS_FC_SAFE;
1619f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (val != prev_val) {
1620f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_xgxs_cfg, val);
1621f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_read_kreg32(dd, kr_scratch);
1622f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1623f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (val & QLOGIC_IB_XGXS_RESET)
1624f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		val &= ~QLOGIC_IB_XGXS_RESET;
1625f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (val != prev_val)
1626f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_xgxs_cfg, val);
1627f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1628f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* first time through, set port guid */
1629f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!ppd->guid)
1630f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->guid = dd->base_guid;
1631f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	guid = be64_to_cpu(ppd->guid);
1632f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1633f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_hrtbt_guid, guid);
1634f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!ret) {
1635f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->control |= QLOGIC_IB_C_LINKENABLE;
1636f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_control, dd->control);
1637f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else
1638f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* write to chip to prevent back-to-back writes of ibc reg */
1639f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_scratch, 0);
1640f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
1641f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1642f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1643f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
1644f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_7220_quiet_serdes - set serdes to txidle
1645f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @ppd: physical port of the qlogic_ib device
1646f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Called when driver is being unloaded
1647f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1648f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_quiet_serdes(struct qib_pportdata *ppd)
1649f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1650f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 val;
1651f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
1652f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
1653f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1654f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* disable IBC */
1655f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->control &= ~QLOGIC_IB_C_LINKENABLE;
1656f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_control,
1657f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		       dd->control | QLOGIC_IB_C_FREEZEMODE);
1658f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1659f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->cpspec->chase_end = 0;
1660f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ppd->cpspec->chase_timer.data) /* if initted */
1661f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		del_timer_sync(&ppd->cpspec->chase_timer);
1662f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1663f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ppd->cpspec->ibsymdelta || ppd->cpspec->iblnkerrdelta ||
1664f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	    ppd->cpspec->ibdeltainprog) {
1665f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u64 diagc;
1666f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1667f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* enable counter writes */
1668f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		diagc = qib_read_kreg64(dd, kr_hwdiagctrl);
1669f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_hwdiagctrl,
1670f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			       diagc | SYM_MASK(HwDiagCtrl, CounterWrEnable));
1671f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1672f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ppd->cpspec->ibsymdelta || ppd->cpspec->ibdeltainprog) {
1673f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			val = read_7220_creg32(dd, cr_ibsymbolerr);
1674f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (ppd->cpspec->ibdeltainprog)
1675f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				val -= val - ppd->cpspec->ibsymsnap;
1676f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			val -= ppd->cpspec->ibsymdelta;
1677f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			write_7220_creg(dd, cr_ibsymbolerr, val);
1678f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1679f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ppd->cpspec->iblnkerrdelta || ppd->cpspec->ibdeltainprog) {
1680f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			val = read_7220_creg32(dd, cr_iblinkerrrecov);
1681f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (ppd->cpspec->ibdeltainprog)
1682f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				val -= val - ppd->cpspec->iblnkerrsnap;
1683f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			val -= ppd->cpspec->iblnkerrdelta;
1684f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			write_7220_creg(dd, cr_iblinkerrrecov, val);
1685f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1686f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1687f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* and disable counter writes */
1688f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_hwdiagctrl, diagc);
1689f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1690f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_set_ib_7220_lstate(ppd, 0, QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
1691f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1692f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&ppd->lflags_lock, flags);
1693f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->lflags &= ~QIBL_IB_AUTONEG_INPROG;
1694f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&ppd->lflags_lock, flags);
1695f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	wake_up(&ppd->cpspec->autoneg_wait);
1696f06267104dd9112f11586830d22501d0e26245eaTejun Heo	cancel_delayed_work_sync(&ppd->cpspec->autoneg_work);
1697f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1698f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	shutdown_7220_relock_poll(ppd->dd);
1699f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	val = qib_read_kreg64(ppd->dd, kr_xgxs_cfg);
1700f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	val |= QLOGIC_IB_XGXS_RESET;
1701f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(ppd->dd, kr_xgxs_cfg, val);
1702f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1703f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1704f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
1705f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_setup_7220_setextled - set the state of the two external LEDs
1706f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dd: the qlogic_ib device
1707f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @on: whether the link is up or not
1708f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
1709f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * The exact combo of LEDs if on is true is determined by looking
1710f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * at the ibcstatus.
1711f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
1712f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * These LEDs indicate the physical and logical state of IB link.
1713f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * For this chip (at least with recommended board pinouts), LED1
1714f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * is Yellow (logical state) and LED2 is Green (physical state),
1715f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
1716f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Note:  We try to match the Mellanox HCA LED behavior as best
1717f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * we can.  Green indicates physical link state is OK (something is
1718f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * plugged in, and we can train).
1719f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Amber indicates the link is logically up (ACTIVE).
1720f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Mellanox further blinks the amber LED to indicate data packet
1721f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * activity, but we have no hardware support for that, so it would
1722f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * require waking up every 10-20 msecs and checking the counters
1723f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * on the chip, and then turning the LED off if appropriate.  That's
1724f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * visible overhead, so not something we will do.
1725f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
1726f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1727f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_setup_7220_setextled(struct qib_pportdata *ppd, u32 on)
1728f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1729f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
1730f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 extctl, ledblink = 0, val, lst, ltst;
1731f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
1732f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1733f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
1734f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * The diags use the LED to indicate diag info, so we leave
1735f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * the external LED alone when the diags are running.
1736f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
1737f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->diag_client)
1738f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		return;
1739f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1740f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ppd->led_override) {
1741f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ltst = (ppd->led_override & QIB_LED_PHYS) ?
1742f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			IB_PHYSPORTSTATE_LINKUP : IB_PHYSPORTSTATE_DISABLED,
1743f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		lst = (ppd->led_override & QIB_LED_LOG) ?
1744f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			IB_PORT_ACTIVE : IB_PORT_DOWN;
1745f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else if (on) {
1746f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		val = qib_read_kreg64(dd, kr_ibcstatus);
1747f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ltst = qib_7220_phys_portstate(val);
1748f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		lst = qib_7220_iblink_state(val);
1749f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else {
1750f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ltst = 0;
1751f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		lst = 0;
1752f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1753f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1754f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&dd->cspec->gpio_lock, flags);
1755f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	extctl = dd->cspec->extctrl & ~(SYM_MASK(EXTCtrl, LEDPriPortGreenOn) |
1756f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				 SYM_MASK(EXTCtrl, LEDPriPortYellowOn));
1757f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ltst == IB_PHYSPORTSTATE_LINKUP) {
1758f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		extctl |= SYM_MASK(EXTCtrl, LEDPriPortGreenOn);
1759f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
1760f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * counts are in chip clock (4ns) periods.
1761f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * This is 1/16 sec (66.6ms) on,
1762f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * 3/16 sec (187.5 ms) off, with packets rcvd
1763f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
1764f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ledblink = ((66600 * 1000UL / 4) << IBA7220_LEDBLINK_ON_SHIFT)
1765f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			| ((187500 * 1000UL / 4) << IBA7220_LEDBLINK_OFF_SHIFT);
1766f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1767f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (lst == IB_PORT_ACTIVE)
1768f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		extctl |= SYM_MASK(EXTCtrl, LEDPriPortYellowOn);
1769f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->extctrl = extctl;
1770f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_extctrl, extctl);
1771f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&dd->cspec->gpio_lock, flags);
1772f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1773f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ledblink) /* blink the LED on packet receive */
1774f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_rcvpktledcnt, ledblink);
1775f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1776f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1777f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_free_irq(struct qib_devdata *dd)
1778f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1779f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->cspec->irq) {
1780f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		free_irq(dd->cspec->irq, dd);
1781f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->irq = 0;
1782f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1783f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_nomsi(dd);
1784f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1785f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1786f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
1787f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_setup_7220_cleanup - clean up any per-chip chip-specific stuff
1788f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dd: the qlogic_ib device
1789f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
1790f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This is called during driver unload.
1791f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
1792f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1793f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_setup_7220_cleanup(struct qib_devdata *dd)
1794f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1795f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_7220_free_irq(dd);
1796f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	kfree(dd->cspec->cntrs);
1797f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	kfree(dd->cspec->portcntrs);
1798f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1799f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1800f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
1801f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This is only called for SDmaInt.
1802f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * SDmaDisabled is handled on the error path.
1803f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1804f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void sdma_7220_intr(struct qib_pportdata *ppd, u64 istat)
1805f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1806f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
1807f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1808f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&ppd->sdma_lock, flags);
1809f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1810f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	switch (ppd->sdma_state.current_state) {
1811f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s00_hw_down:
1812f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
1813f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1814f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s10_hw_start_up_wait:
1815f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		__qib_sdma_process_event(ppd, qib_sdma_event_e20_hw_started);
1816f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
1817f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1818f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s20_idle:
1819f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
1820f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1821f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s30_sw_clean_up_wait:
1822f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
1823f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1824f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s40_hw_clean_up_wait:
1825f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
1826f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1827f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s50_hw_halt_wait:
1828f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		__qib_sdma_process_event(ppd, qib_sdma_event_e60_hw_halted);
1829f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
1830f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1831f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case qib_sdma_state_s99_running:
1832f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* too chatty to print here */
1833f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		__qib_sdma_intr(ppd);
1834f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
1835f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1836f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&ppd->sdma_lock, flags);
1837f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1838f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1839f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_wantpiobuf_7220_intr(struct qib_devdata *dd, u32 needint)
1840f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1841f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
1842f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1843f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&dd->sendctrl_lock, flags);
1844f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (needint) {
1845f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!(dd->sendctrl & SYM_MASK(SendCtrl, SendBufAvailUpd)))
1846f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto done;
1847f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
1848f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * blip the availupd off, next write will be on, so
1849f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * we ensure an avail update, regardless of threshold or
1850f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * buffers becoming free, whenever we want an interrupt
1851f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
1852f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_sendctrl, dd->sendctrl &
1853f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			~SYM_MASK(SendCtrl, SendBufAvailUpd));
1854f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_scratch, 0ULL);
1855f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->sendctrl |= SYM_MASK(SendCtrl, SendIntBufAvail);
1856f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else
1857f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->sendctrl &= ~SYM_MASK(SendCtrl, SendIntBufAvail);
1858f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_sendctrl, dd->sendctrl);
1859f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_scratch, 0ULL);
1860f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbelldone:
1861f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&dd->sendctrl_lock, flags);
1862f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1863f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1864f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
1865f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Handle errors and unusual events first, separate function
1866f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * to improve cache hits for fast path interrupt handling.
1867f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
1868f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic noinline void unlikely_7220_intr(struct qib_devdata *dd, u64 istat)
1869f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1870f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (unlikely(istat & ~QLOGIC_IB_I_BITSEXTANT))
1871f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd,
1872f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    "interrupt with unknown interrupts %Lx set\n",
1873f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    istat & ~QLOGIC_IB_I_BITSEXTANT);
1874f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1875f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (istat & QLOGIC_IB_I_GPIO) {
1876f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u32 gpiostatus;
1877f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1878f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
1879f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Boards for this chip currently don't use GPIO interrupts,
1880f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * so clear by writing GPIOstatus to GPIOclear, and complain
1881f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * to alert developer. To avoid endless repeats, clear
1882f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * the bits in the mask, since there is some kind of
1883f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * programming error or chip problem.
1884f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
1885f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		gpiostatus = qib_read_kreg32(dd, kr_gpio_status);
1886f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
1887f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * In theory, writing GPIOstatus to GPIOclear could
1888f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * have a bad side-effect on some diagnostic that wanted
1889f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * to poll for a status-change, but the various shadows
1890f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * make that problematic at best. Diags will just suppress
1891f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * all GPIO interrupts during such tests.
1892f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
1893f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_gpio_clear, gpiostatus);
1894f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1895f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (gpiostatus) {
1896f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			const u32 mask = qib_read_kreg32(dd, kr_gpio_mask);
1897f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			u32 gpio_irq = mask & gpiostatus;
1898f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1899f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/*
1900f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * A bit set in status and (chip) Mask register
1901f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * would cause an interrupt. Since we are not
1902f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * expecting any, report it. Also check that the
1903f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * chip reflects our shadow, report issues,
1904f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * and refresh from the shadow.
1905f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 */
1906f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/*
1907f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * Clear any troublemakers, and update chip
1908f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * from shadow
1909f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 */
1910f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->cspec->gpio_mask &= ~gpio_irq;
1911f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_write_kreg(dd, kr_gpio_mask, dd->cspec->gpio_mask);
1912f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1913f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1914f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1915f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (istat & QLOGIC_IB_I_ERROR) {
1916f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u64 estat;
1917f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1918f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_stats.sps_errints++;
1919f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		estat = qib_read_kreg64(dd, kr_errstatus);
1920f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!estat)
1921f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_devinfo(dd->pcidev, "error interrupt (%Lx), "
1922f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				 "but no error bits set!\n", istat);
1923f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		else
1924f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			handle_7220_errors(dd, estat);
1925f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1926f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
1927f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1928f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic irqreturn_t qib_7220intr(int irq, void *data)
1929f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
1930f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = data;
1931f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	irqreturn_t ret;
1932f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 istat;
1933f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 ctxtrbits;
1934f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 rmask;
1935f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned i;
1936f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1937f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if ((dd->flags & (QIB_PRESENT | QIB_BADINTR)) != QIB_PRESENT) {
1938f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
1939f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * This return value is not great, but we do not want the
1940f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * interrupt core code to remove our interrupt handler
1941f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * because we don't appear to be handling an interrupt
1942f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * during a chip reset.
1943f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
1944f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = IRQ_HANDLED;
1945f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
1946f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1947f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1948f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	istat = qib_read_kreg64(dd, kr_intstatus);
1949f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1950f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (unlikely(!istat)) {
1951f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = IRQ_NONE; /* not our interrupt, or already handled */
1952f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
1953f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1954f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (unlikely(istat == -1)) {
1955f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_bad_intrstatus(dd);
1956f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* don't know if it was our interrupt or not */
1957f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = IRQ_NONE;
1958f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
1959f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
1960f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1961f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_stats.sps_ints++;
1962f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->int_counter != (u32) -1)
1963f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->int_counter++;
1964f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1965f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (unlikely(istat & (~QLOGIC_IB_I_BITSEXTANT |
1966f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			      QLOGIC_IB_I_GPIO | QLOGIC_IB_I_ERROR)))
1967f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		unlikely_7220_intr(dd, istat);
1968f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1969f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
1970f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Clear the interrupt bits we found set, relatively early, so we
1971f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * "know" know the chip will have seen this by the time we process
1972f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * the queue, and will re-interrupt if necessary.  The processor
1973f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * itself won't take the interrupt again until we return.
1974f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
1975f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_intclear, istat);
1976f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
1977f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
1978f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Handle kernel receive queues before checking for pio buffers
1979f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * available since receives can overflow; piobuf waiters can afford
1980f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * a few extra cycles, since they were waiting anyway.
1981f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
1982f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ctxtrbits = istat &
1983f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		((QLOGIC_IB_I_RCVAVAIL_MASK << QLOGIC_IB_I_RCVAVAIL_SHIFT) |
1984f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 (QLOGIC_IB_I_RCVURG_MASK << QLOGIC_IB_I_RCVURG_SHIFT));
1985f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ctxtrbits) {
1986f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		rmask = (1ULL << QLOGIC_IB_I_RCVAVAIL_SHIFT) |
1987f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			(1ULL << QLOGIC_IB_I_RCVURG_SHIFT);
1988f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		for (i = 0; i < dd->first_user_ctxt; i++) {
1989f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (ctxtrbits & rmask) {
1990f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ctxtrbits &= ~rmask;
1991f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qib_kreceive(dd->rcd[i], NULL, NULL);
1992f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
1993f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			rmask <<= 1;
1994f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
1995f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ctxtrbits) {
1996f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ctxtrbits =
1997f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				(ctxtrbits >> QLOGIC_IB_I_RCVAVAIL_SHIFT) |
1998f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				(ctxtrbits >> QLOGIC_IB_I_RCVURG_SHIFT);
1999f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_handle_urcv(dd, ctxtrbits);
2000f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
2001f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2002f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2003f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* only call for SDmaInt */
2004f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (istat & QLOGIC_IB_I_SDMAINT)
2005f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sdma_7220_intr(dd->pport, istat);
2006f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2007f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if ((istat & QLOGIC_IB_I_SPIOBUFAVAIL) && (dd->flags & QIB_INITTED))
2008f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_ib_piobufavail(dd);
2009f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2010f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = IRQ_HANDLED;
2011f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail:
2012f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
2013f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2014f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2015f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
2016f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Set up our chip-specific interrupt handler.
2017f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * The interrupt type has already been setup, so
2018f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * we just need to do the registration and error checking.
2019f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * If we are using MSI interrupts, we may fall back to
2020f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * INTx later, if the interrupt handler doesn't get called
2021f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * within 1/2 second (see verify_interrupt()).
2022f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
2023f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_setup_7220_interrupt(struct qib_devdata *dd)
2024f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2025f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!dd->cspec->irq)
2026f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "irq is 0, BIOS error?  Interrupts won't "
2027f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    "work\n");
2028f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else {
2029f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		int ret = request_irq(dd->cspec->irq, qib_7220intr,
2030f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->msi_lo ? 0 : IRQF_SHARED,
2031f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			QIB_DRV_NAME, dd);
2032f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2033f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ret)
2034f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_dev_err(dd, "Couldn't setup %s interrupt "
2035f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				    "(irq=%d): %d\n", dd->msi_lo ?
2036f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				    "MSI" : "INTx", dd->cspec->irq, ret);
2037f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2038f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2039f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2040f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
2041f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_7220_boardname - fill in the board name
2042f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dd: the qlogic_ib device
2043f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
2044f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * info is based on the board revision register
2045f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
2046f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_boardname(struct qib_devdata *dd)
2047f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2048f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	char *n;
2049f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 boardid, namelen;
2050f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2051f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	boardid = SYM_FIELD(dd->revision, Revision,
2052f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    BoardID);
2053f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2054f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	switch (boardid) {
2055f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case 1:
2056f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		n = "InfiniPath_QLE7240";
2057f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
2058f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case 2:
2059f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		n = "InfiniPath_QLE7280";
2060f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
2061f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	default:
2062f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "Unknown 7220 board with ID %u\n", boardid);
2063f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		n = "Unknown_InfiniPath_7220";
2064f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
2065f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2066f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2067f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	namelen = strlen(n) + 1;
2068f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->boardname = kmalloc(namelen, GFP_KERNEL);
2069f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!dd->boardname)
2070f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "Failed allocation for board name: %s\n", n);
2071f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
2072f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		snprintf(dd->boardname, namelen, "%s", n);
2073f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2074f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->majrev != 5 || !dd->minrev || dd->minrev > 2)
2075f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "Unsupported InfiniPath hardware "
2076f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    "revision %u.%u!\n",
2077f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    dd->majrev, dd->minrev);
2078f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2079f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	snprintf(dd->boardversion, sizeof(dd->boardversion),
2080f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 "ChipABI %u.%u, %s, InfiniPath%u %u.%u, SW Compat %u\n",
2081f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 QIB_CHIP_VERS_MAJ, QIB_CHIP_VERS_MIN, dd->boardname,
2082f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 (unsigned)SYM_FIELD(dd->revision, Revision_R, Arch),
2083f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 dd->majrev, dd->minrev,
2084f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 (unsigned)SYM_FIELD(dd->revision, Revision_R, SW));
2085f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2086f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2087f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
2088f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This routine sleeps, so it can only be called from user context, not
2089f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * from interrupt context.
2090f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
2091f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_setup_7220_reset(struct qib_devdata *dd)
2092f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2093f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 val;
2094f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int i;
2095f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int ret;
2096f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u16 cmdval;
2097f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u8 int_line, clinesz;
2098f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
2099f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2100f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_pcie_getcmd(dd, &cmdval, &int_line, &clinesz);
2101f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2102f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* Use dev_err so it shows up in logs, etc. */
2103f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_dev_err(dd, "Resetting InfiniPath unit %u\n", dd->unit);
2104f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2105f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* no interrupts till re-initted */
2106f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_7220_set_intr_state(dd, 0);
2107f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2108f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->pport->cpspec->ibdeltainprog = 0;
2109f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->pport->cpspec->ibsymdelta = 0;
2110f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->pport->cpspec->iblnkerrdelta = 0;
2111f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2112f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
2113f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Keep chip from being accessed until we are ready.  Use
2114f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * writeq() directly, to allow the write even though QIB_PRESENT
2115e9c549998dc24209847007e1f209f3b6c88d21baLucas De Marchi	 * isn't set.
2116f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
2117f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->flags &= ~(QIB_INITTED | QIB_PRESENT);
2118f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->int_counter = 0; /* so we check interrupts work again */
2119f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	val = dd->control | QLOGIC_IB_C_RESET;
2120f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	writeq(val, &dd->kregbase[kr_control]);
2121f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	mb(); /* prevent compiler reordering around actual reset */
2122f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2123f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (i = 1; i <= 5; i++) {
2124f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
2125f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Allow MBIST, etc. to complete; longer on each retry.
2126f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * We sometimes get machine checks from bus timeout if no
2127f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * response, so for now, make it *really* long.
2128f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
2129f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		msleep(1000 + (1 + i) * 2000);
2130f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2131f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_pcie_reenable(dd, cmdval, int_line, clinesz);
2132f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2133f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
2134f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Use readq directly, so we don't need to mark it as PRESENT
2135f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * until we get a successful indication that all is well.
2136f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
2137f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		val = readq(&dd->kregbase[kr_revision]);
2138f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (val == dd->revision) {
2139f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->flags |= QIB_PRESENT; /* it's back */
2140f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = qib_reinit_intr(dd);
2141f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto bail;
2142f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
2143f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2144f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = 0; /* failed */
2145f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2146f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail:
2147f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ret) {
2148f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qib_pcie_params(dd, dd->lbus_width, NULL, NULL))
2149f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_dev_err(dd, "Reset failed to setup PCIe or "
2150f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				    "interrupts; continuing anyway\n");
2151f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2152f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* hold IBC in reset, no sends, etc till later */
2153f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_control, 0ULL);
2154f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2155f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* clear the reset error, init error/hwerror mask */
2156f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_7220_init_hwerrors(dd);
2157f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2158f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* do setup similar to speed or link-width changes */
2159f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (dd->pport->cpspec->ibcddrctrl & IBA7220_IBC_IBTA_1_2_MASK)
2160f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->cspec->presets_needed = 1;
2161f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock_irqsave(&dd->pport->lflags_lock, flags);
2162f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->pport->lflags |= QIBL_IB_FORCE_NOTIFY;
2163f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->pport->lflags &= ~QIBL_IB_AUTONEG_FAILED;
2164f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock_irqrestore(&dd->pport->lflags_lock, flags);
2165f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2166f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2167f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
2168f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2169f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2170f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
2171f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_7220_put_tid - write a TID to the chip
2172f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dd: the qlogic_ib device
2173f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @tidptr: pointer to the expected TID (in chip) to update
2174f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @tidtype: 0 for eager, 1 for expected
2175f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @pa: physical address of in memory buffer; tidinvalid if freeing
2176f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
2177f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_put_tid(struct qib_devdata *dd, u64 __iomem *tidptr,
2178f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			     u32 type, unsigned long pa)
2179f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2180f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (pa != dd->tidinvalid) {
2181f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u64 chippa = pa >> IBA7220_TID_PA_SHIFT;
2182f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2183f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* paranoia checks */
2184f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (pa != (chippa << IBA7220_TID_PA_SHIFT)) {
2185f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_dev_err(dd, "Physaddr %lx not 2KB aligned!\n",
2186f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				    pa);
2187f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			return;
2188f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
2189f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (chippa >= (1UL << IBA7220_TID_SZ_SHIFT)) {
2190f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_dev_err(dd, "Physical page address 0x%lx "
2191f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				"larger than supported\n", pa);
2192f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			return;
2193f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
2194f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2195f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (type == RCVHQ_RCV_TYPE_EAGER)
2196f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			chippa |= dd->tidtemplate;
2197f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		else /* for now, always full 4KB page */
2198f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			chippa |= IBA7220_TID_SZ_4K;
2199f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		pa = chippa;
2200f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2201f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	writeq(pa, tidptr);
2202f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	mmiowb();
2203f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2204f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2205f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
2206f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_7220_clear_tids - clear all TID entries for a ctxt, expected and eager
2207f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dd: the qlogic_ib device
2208f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @ctxt: the ctxt
2209f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
2210f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * clear all TID entries for a ctxt, expected and eager.
2211f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Used from qib_close().  On this chip, TIDs are only 32 bits,
2212f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * not 64, but they are still on 64 bit boundaries, so tidbase
2213f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * is declared as u64 * for the pointer math, even though we write 32 bits
2214f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
2215f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_clear_tids(struct qib_devdata *dd,
2216f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				struct qib_ctxtdata *rcd)
2217f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2218f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 __iomem *tidbase;
2219f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long tidinv;
2220f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 ctxt;
2221f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int i;
2222f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2223f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!dd->kregbase || !rcd)
2224f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		return;
2225f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2226f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ctxt = rcd->ctxt;
2227f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2228f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	tidinv = dd->tidinvalid;
2229f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	tidbase = (u64 __iomem *)
2230f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		((char __iomem *)(dd->kregbase) +
2231f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 dd->rcvtidbase +
2232f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 ctxt * dd->rcvtidcnt * sizeof(*tidbase));
2233f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2234f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (i = 0; i < dd->rcvtidcnt; i++)
2235f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_7220_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED,
2236f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				 tidinv);
2237f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2238f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	tidbase = (u64 __iomem *)
2239f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		((char __iomem *)(dd->kregbase) +
2240f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 dd->rcvegrbase +
2241f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 rcd->rcvegr_tid_base * sizeof(*tidbase));
2242f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2243f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (i = 0; i < rcd->rcvegrcnt; i++)
2244f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_7220_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EAGER,
2245f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				 tidinv);
2246f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2247f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2248f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
2249f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_7220_tidtemplate - setup constants for TID updates
2250f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dd: the qlogic_ib device
2251f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
2252f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * We setup stuff that we use a lot, to avoid calculating each time
2253f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
2254f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_tidtemplate(struct qib_devdata *dd)
2255f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2256f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->rcvegrbufsize == 2048)
2257f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->tidtemplate = IBA7220_TID_SZ_2K;
2258f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else if (dd->rcvegrbufsize == 4096)
2259f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->tidtemplate = IBA7220_TID_SZ_4K;
2260f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->tidinvalid = 0;
2261f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2262f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2263f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
2264f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_init_7220_get_base_info - set chip-specific flags for user code
2265f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @rcd: the qlogic_ib ctxt
2266f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @kbase: qib_base_info pointer
2267f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
2268f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * We set the PCIE flag because the lower bandwidth on PCIe vs
2269f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * HyperTransport can affect some user packet algorithims.
2270f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
2271f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_7220_get_base_info(struct qib_ctxtdata *rcd,
2272f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				  struct qib_base_info *kinfo)
2273f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2274f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	kinfo->spi_runtime_flags |= QIB_RUNTIME_PCIE |
2275f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QIB_RUNTIME_NODMA_RTAIL | QIB_RUNTIME_SDMA;
2276f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2277f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (rcd->dd->flags & QIB_USE_SPCL_TRIG)
2278f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		kinfo->spi_runtime_flags |= QIB_RUNTIME_SPECIAL_TRIGGER;
2279f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2280f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return 0;
2281f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2282f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2283f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic struct qib_message_header *
2284f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellqib_7220_get_msgheader(struct qib_devdata *dd, __le32 *rhf_addr)
2285f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2286f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 offset = qib_hdrget_offset(rhf_addr);
2287f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2288f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return (struct qib_message_header *)
2289f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		(rhf_addr - dd->rhf_offset + offset);
2290f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2291f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2292f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_config_ctxts(struct qib_devdata *dd)
2293f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2294f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
2295f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 nchipctxts;
2296f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2297f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	nchipctxts = qib_read_kreg32(dd, kr_portcnt);
2298f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->numctxts = nchipctxts;
2299f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qib_n_krcv_queues > 1) {
23002528ea60f94ef9e1e1cd82066d55f62a1d19fde1Mike Marciniszyn		dd->qpn_mask = 0x3e;
2301f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->first_user_ctxt = qib_n_krcv_queues * dd->num_pports;
2302f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (dd->first_user_ctxt > nchipctxts)
2303f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->first_user_ctxt = nchipctxts;
2304f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else
2305f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->first_user_ctxt = dd->num_pports;
2306f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->n_krcv_queues = dd->first_user_ctxt;
2307f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2308f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!qib_cfgctxts) {
2309f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		int nctxts = dd->first_user_ctxt + num_online_cpus();
2310f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2311f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (nctxts <= 5)
2312f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->ctxtcnt = 5;
2313f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		else if (nctxts <= 9)
2314f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->ctxtcnt = 9;
2315f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		else if (nctxts <= nchipctxts)
2316f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->ctxtcnt = nchipctxts;
2317f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else if (qib_cfgctxts <= nchipctxts)
2318f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->ctxtcnt = qib_cfgctxts;
2319f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!dd->ctxtcnt) /* none of the above, set to max */
2320f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->ctxtcnt = nchipctxts;
2321f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2322f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
2323f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Chip can be configured for 5, 9, or 17 ctxts, and choice
2324f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * affects number of eager TIDs per ctxt (1K, 2K, 4K).
2325f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Lock to be paranoid about later motion, etc.
2326f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
2327f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags);
2328f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->ctxtcnt > 9)
2329f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcvctrl |= 2ULL << IBA7220_R_CTXTCFG_SHIFT;
2330f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else if (dd->ctxtcnt > 5)
2331f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcvctrl |= 1ULL << IBA7220_R_CTXTCFG_SHIFT;
2332f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* else configure for default 5 receive ctxts */
2333f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->qpn_mask)
2334f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcvctrl |= 1ULL << QIB_7220_RcvCtrl_RcvQPMapEnable_LSB;
2335f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_rcvctrl, dd->rcvctrl);
2336f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&dd->cspec->rcvmod_lock, flags);
2337f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2338f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* kr_rcvegrcnt changes based on the number of contexts enabled */
2339f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->rcvegrcnt = qib_read_kreg32(dd, kr_rcvegrcnt);
2340f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->rcvhdrcnt = max(dd->cspec->rcvegrcnt, IBA7220_KRCVEGRCNT);
2341f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2342f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2343f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_7220_get_ib_cfg(struct qib_pportdata *ppd, int which)
2344f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2345f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int lsb, ret = 0;
2346f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 maskr; /* right-justified mask */
2347f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2348f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	switch (which) {
2349f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_LWID_ENB: /* Get allowed Link-width */
2350f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = ppd->link_width_enabled;
2351f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2352f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2353f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_LWID: /* Get currently active Link-width */
2354f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = ppd->link_width_active;
2355f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2356f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2357f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_SPD_ENB: /* Get allowed Link speeds */
2358f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = ppd->link_speed_enabled;
2359f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2360f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2361f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_SPD: /* Get current Link spd */
2362f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = ppd->link_speed_active;
2363f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2364f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2365f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_RXPOL_ENB: /* Get Auto-RX-polarity enable */
2366f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		lsb = IBA7220_IBC_RXPOL_SHIFT;
2367f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		maskr = IBA7220_IBC_RXPOL_MASK;
2368f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
2369f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2370f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_LREV_ENB: /* Get Auto-Lane-reversal enable */
2371f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		lsb = IBA7220_IBC_LREV_SHIFT;
2372f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		maskr = IBA7220_IBC_LREV_MASK;
2373f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
2374f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2375f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_LINKLATENCY:
2376f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = qib_read_kreg64(ppd->dd, kr_ibcddrstatus)
2377f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			& IBA7220_DDRSTAT_LINKLAT_MASK;
2378f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2379f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2380f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_OP_VLS:
2381f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = ppd->vls_operational;
2382f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2383f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2384f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_VL_HIGH_CAP:
2385f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = 0;
2386f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2387f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2388f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_VL_LOW_CAP:
2389f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = 0;
2390f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2391f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2392f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_OVERRUN_THRESH: /* IB overrun threshold */
2393f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = SYM_FIELD(ppd->cpspec->ibcctrl, IBCCtrl,
2394f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				OverrunThreshold);
2395f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2396f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2397f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_PHYERR_THRESH: /* IB PHY error threshold */
2398f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = SYM_FIELD(ppd->cpspec->ibcctrl, IBCCtrl,
2399f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				PhyerrThreshold);
2400f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2401f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2402f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_LINKDEFAULT: /* IB link default (sleep/poll) */
2403f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* will only take effect when the link state changes */
2404f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = (ppd->cpspec->ibcctrl &
2405f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		       SYM_MASK(IBCCtrl, LinkDownDefaultState)) ?
2406f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			IB_LINKINITCMD_SLEEP : IB_LINKINITCMD_POLL;
2407f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2408f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2409f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_HRTBT: /* Get Heartbeat off/enable/auto */
2410f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		lsb = IBA7220_IBC_HRTBT_SHIFT;
2411f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		maskr = IBA7220_IBC_HRTBT_MASK;
2412f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
2413f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2414f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_PMA_TICKS:
2415f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
2416f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * 0x00 = 10x link transfer rate or 4 nsec. for 2.5Gbs
2417f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Since the clock is always 250MHz, the value is 1 or 0.
2418f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
2419f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = (ppd->link_speed_active == QIB_IB_DDR);
2420f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2421f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2422f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	default:
2423f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = -EINVAL;
2424f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2425f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2426f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = (int)((ppd->cpspec->ibcddrctrl >> lsb) & maskr);
2427f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbelldone:
2428f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
2429f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2430f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2431f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val)
2432f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2433f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
2434f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 maskr; /* right-justified mask */
2435f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int lsb, ret = 0, setforce = 0;
2436f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u16 lcmd, licmd;
2437f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
2438e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov	u32 tmp = 0;
2439f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2440f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	switch (which) {
2441f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_LIDLMC:
2442f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
2443f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Set LID and LMC. Combined to avoid possible hazard
2444f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * caller puts LMC in 16MSbits, DLID in 16LSbits of val
2445f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
2446f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		lsb = IBA7220_IBC_DLIDLMC_SHIFT;
2447f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		maskr = IBA7220_IBC_DLIDLMC_MASK;
2448f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
2449f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2450f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_LWID_ENB: /* set allowed Link-width */
2451f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
2452f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * As with speed, only write the actual register if
2453f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * the link is currently down, otherwise takes effect
2454f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * on next link change.
2455f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
2456f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->link_width_enabled = val;
2457f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!(ppd->lflags & QIBL_LINKDOWN))
2458f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto bail;
2459f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
2460f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * We set the QIBL_IB_FORCE_NOTIFY bit so updown
2461f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * will get called because we want update
2462f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * link_width_active, and the change may not take
2463f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * effect for some time (if we are in POLL), so this
2464f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * flag will force the updown routine to be called
2465f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * on the next ibstatuschange down interrupt, even
2466f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * if it's not an down->up transition.
2467f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
2468f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		val--; /* convert from IB to chip */
2469f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		maskr = IBA7220_IBC_WIDTH_MASK;
2470f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		lsb = IBA7220_IBC_WIDTH_SHIFT;
2471f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		setforce = 1;
2472f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
2473f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2474f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_SPD_ENB: /* set allowed Link speeds */
2475f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
2476f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * If we turn off IB1.2, need to preset SerDes defaults,
2477f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * but not right now. Set a flag for the next time
2478f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * we command the link down.  As with width, only write the
2479f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * actual register if the link is currently down, otherwise
2480f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * takes effect on next link change.  Since setting is being
248125985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		 * explicitly requested (via MAD or sysfs), clear autoneg
2482f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * failure status if speed autoneg is enabled.
2483f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
2484f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->link_speed_enabled = val;
2485f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if ((ppd->cpspec->ibcddrctrl & IBA7220_IBC_IBTA_1_2_MASK) &&
2486f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    !(val & (val - 1)))
2487f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->cspec->presets_needed = 1;
2488f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!(ppd->lflags & QIBL_LINKDOWN))
2489f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto bail;
2490f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
2491f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * We set the QIBL_IB_FORCE_NOTIFY bit so updown
2492f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * will get called because we want update
2493f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * link_speed_active, and the change may not take
2494f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * effect for some time (if we are in POLL), so this
2495f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * flag will force the updown routine to be called
2496f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * on the next ibstatuschange down interrupt, even
2497f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * if it's not an down->up transition.
2498f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
2499f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (val == (QIB_IB_SDR | QIB_IB_DDR)) {
2500f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			val = IBA7220_IBC_SPEED_AUTONEG_MASK |
2501f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				IBA7220_IBC_IBTA_1_2_MASK;
2502f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_lock_irqsave(&ppd->lflags_lock, flags);
2503f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->lflags &= ~QIBL_IB_AUTONEG_FAILED;
2504f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_unlock_irqrestore(&ppd->lflags_lock, flags);
2505f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else
2506f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			val = val == QIB_IB_DDR ?
2507f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				IBA7220_IBC_SPEED_DDR : IBA7220_IBC_SPEED_SDR;
2508f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		maskr = IBA7220_IBC_SPEED_AUTONEG_MASK |
2509f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			IBA7220_IBC_IBTA_1_2_MASK;
2510f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* IBTA 1.2 mode + speed bits are contiguous */
2511f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		lsb = SYM_LSB(IBCDDRCtrl, IB_ENHANCED_MODE);
2512f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		setforce = 1;
2513f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
2514f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2515f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_RXPOL_ENB: /* set Auto-RX-polarity enable */
2516f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		lsb = IBA7220_IBC_RXPOL_SHIFT;
2517f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		maskr = IBA7220_IBC_RXPOL_MASK;
2518f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
2519f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2520f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_LREV_ENB: /* set Auto-Lane-reversal enable */
2521f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		lsb = IBA7220_IBC_LREV_SHIFT;
2522f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		maskr = IBA7220_IBC_LREV_MASK;
2523f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
2524f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2525f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_OVERRUN_THRESH: /* IB overrun threshold */
2526f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		maskr = SYM_FIELD(ppd->cpspec->ibcctrl, IBCCtrl,
2527f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				  OverrunThreshold);
2528f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (maskr != val) {
2529f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->ibcctrl &=
2530f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				~SYM_MASK(IBCCtrl, OverrunThreshold);
2531f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->ibcctrl |= (u64) val <<
2532f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				SYM_LSB(IBCCtrl, OverrunThreshold);
2533f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_write_kreg(dd, kr_ibcctrl, ppd->cpspec->ibcctrl);
2534f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_write_kreg(dd, kr_scratch, 0);
2535f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
2536f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
2537f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2538f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_PHYERR_THRESH: /* IB PHY error threshold */
2539f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		maskr = SYM_FIELD(ppd->cpspec->ibcctrl, IBCCtrl,
2540f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				  PhyerrThreshold);
2541f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (maskr != val) {
2542f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->ibcctrl &=
2543f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				~SYM_MASK(IBCCtrl, PhyerrThreshold);
2544f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->ibcctrl |= (u64) val <<
2545f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				SYM_LSB(IBCCtrl, PhyerrThreshold);
2546f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_write_kreg(dd, kr_ibcctrl, ppd->cpspec->ibcctrl);
2547f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_write_kreg(dd, kr_scratch, 0);
2548f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
2549f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
2550f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2551f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_PKEYS: /* update pkeys */
2552f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		maskr = (u64) ppd->pkeys[0] | ((u64) ppd->pkeys[1] << 16) |
2553f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			((u64) ppd->pkeys[2] << 32) |
2554f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			((u64) ppd->pkeys[3] << 48);
2555f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_partitionkey, maskr);
2556f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
2557f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2558f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_LINKDEFAULT: /* IB link default (sleep/poll) */
2559f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* will only take effect when the link state changes */
2560f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (val == IB_LINKINITCMD_POLL)
2561f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->ibcctrl &=
2562f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				~SYM_MASK(IBCCtrl, LinkDownDefaultState);
2563f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		else /* SLEEP */
2564f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->ibcctrl |=
2565f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				SYM_MASK(IBCCtrl, LinkDownDefaultState);
2566f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_ibcctrl, ppd->cpspec->ibcctrl);
2567f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_scratch, 0);
2568f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
2569f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2570f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_MTU: /* update the MTU in IBC */
2571f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
2572f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Update our housekeeping variables, and set IBC max
2573f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * size, same as init code; max IBC is max we allow in
2574f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * buffer, less the qword pbc, plus 1 for ICRC, in dwords
2575f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Set even if it's unchanged, print debug message only
2576f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * on changes.
2577f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
2578f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		val = (ppd->ibmaxlen >> 2) + 1;
2579f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibcctrl &= ~SYM_MASK(IBCCtrl, MaxPktLen);
2580f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibcctrl |= (u64)val << SYM_LSB(IBCCtrl, MaxPktLen);
2581f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_ibcctrl, ppd->cpspec->ibcctrl);
2582f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_scratch, 0);
2583f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
2584f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2585f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_LSTATE: /* set the IB link state */
2586f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		switch (val & 0xffff0000) {
2587f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		case IB_LINKCMD_DOWN:
2588f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			lcmd = QLOGIC_IB_IBCC_LINKCMD_DOWN;
2589f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (!ppd->cpspec->ibdeltainprog &&
2590f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    qib_compat_ddr_negotiate) {
2591f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->cpspec->ibdeltainprog = 1;
2592f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->cpspec->ibsymsnap =
2593f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					read_7220_creg32(dd, cr_ibsymbolerr);
2594f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->cpspec->iblnkerrsnap =
2595f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					read_7220_creg32(dd, cr_iblinkerrrecov);
2596f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
2597f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			break;
2598f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2599f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		case IB_LINKCMD_ARMED:
2600f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			lcmd = QLOGIC_IB_IBCC_LINKCMD_ARMED;
2601f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			break;
2602f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2603f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		case IB_LINKCMD_ACTIVE:
2604f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			lcmd = QLOGIC_IB_IBCC_LINKCMD_ACTIVE;
2605f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			break;
2606f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2607f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		default:
2608f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = -EINVAL;
2609f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_dev_err(dd, "bad linkcmd req 0x%x\n", val >> 16);
2610f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto bail;
2611f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
2612f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		switch (val & 0xffff) {
2613f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		case IB_LINKINITCMD_NOP:
2614f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			licmd = 0;
2615f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			break;
2616f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2617f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		case IB_LINKINITCMD_POLL:
2618f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			licmd = QLOGIC_IB_IBCC_LINKINITCMD_POLL;
2619f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			break;
2620f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2621f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		case IB_LINKINITCMD_SLEEP:
2622f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			licmd = QLOGIC_IB_IBCC_LINKINITCMD_SLEEP;
2623f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			break;
2624f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2625f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		case IB_LINKINITCMD_DISABLE:
2626f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			licmd = QLOGIC_IB_IBCC_LINKINITCMD_DISABLE;
2627f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->chase_end = 0;
2628f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/*
2629f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * stop state chase counter and timer, if running.
2630f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * wait forpending timer, but don't clear .data (ppd)!
2631f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 */
2632f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (ppd->cpspec->chase_timer.expires) {
2633f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				del_timer_sync(&ppd->cpspec->chase_timer);
2634f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->cpspec->chase_timer.expires = 0;
2635f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
2636f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			break;
2637f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2638f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		default:
2639f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = -EINVAL;
2640f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_dev_err(dd, "bad linkinitcmd req 0x%x\n",
2641f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				    val & 0xffff);
2642f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto bail;
2643f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
2644f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_set_ib_7220_lstate(ppd, lcmd, licmd);
2645e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov
2646e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov		maskr = IBA7220_IBC_WIDTH_MASK;
2647e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov		lsb = IBA7220_IBC_WIDTH_SHIFT;
2648e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov		tmp = (ppd->cpspec->ibcddrctrl >> lsb) & maskr;
2649e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov		/* If the width active on the chip does not match the
2650e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov		 * width in the shadow register, write the new active
2651e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov		 * width to the chip.
2652e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov		 * We don't have to worry about speed as the speed is taken
2653e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov		 * care of by set_7220_ibspeed_fast called by ib_updown.
2654e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov		 */
2655e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov		if (ppd->link_width_enabled-1 != tmp) {
2656e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov			ppd->cpspec->ibcddrctrl &= ~(maskr << lsb);
2657e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov			ppd->cpspec->ibcddrctrl |=
2658e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov				(((u64)(ppd->link_width_enabled-1) & maskr) <<
2659e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov				 lsb);
2660e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov			qib_write_kreg(dd, kr_ibcddrctrl,
2661e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov				       ppd->cpspec->ibcddrctrl);
2662e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov			qib_write_kreg(dd, kr_scratch, 0);
2663e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov			spin_lock_irqsave(&ppd->lflags_lock, flags);
2664e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov			ppd->lflags |= QIBL_IB_FORCE_NOTIFY;
2665e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov			spin_unlock_irqrestore(&ppd->lflags_lock, flags);
2666e800bd032c2623b10ef38a4d7d646e3e3c7bb3adMitko Haralanov		}
2667f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
2668f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2669f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case QIB_IB_CFG_HRTBT: /* set Heartbeat off/enable/auto */
2670f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (val > IBA7220_IBC_HRTBT_MASK) {
2671f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = -EINVAL;
2672f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto bail;
2673f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
2674f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		lsb = IBA7220_IBC_HRTBT_SHIFT;
2675f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		maskr = IBA7220_IBC_HRTBT_MASK;
2676f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
2677f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2678f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	default:
2679f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = -EINVAL;
2680f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
2681f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2682f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->cpspec->ibcddrctrl &= ~(maskr << lsb);
2683f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->cpspec->ibcddrctrl |= (((u64) val & maskr) << lsb);
2684f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_ibcddrctrl, ppd->cpspec->ibcddrctrl);
2685f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_scratch, 0);
2686f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (setforce) {
2687f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock_irqsave(&ppd->lflags_lock, flags);
2688f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->lflags |= QIBL_IB_FORCE_NOTIFY;
2689f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
2690f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2691f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail:
2692f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
2693f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2694f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2695f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_7220_set_loopback(struct qib_pportdata *ppd, const char *what)
2696f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2697f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int ret = 0;
2698f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 val, ddr;
2699f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2700f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!strncmp(what, "ibc", 3)) {
2701f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibcctrl |= SYM_MASK(IBCCtrl, Loopback);
2702f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		val = 0; /* disable heart beat, so link will come up */
2703f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_devinfo(ppd->dd->pcidev, "Enabling IB%u:%u IBC loopback\n",
2704f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 ppd->dd->unit, ppd->port);
2705f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else if (!strncmp(what, "off", 3)) {
2706f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibcctrl &= ~SYM_MASK(IBCCtrl, Loopback);
2707f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* enable heart beat again */
2708f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		val = IBA7220_IBC_HRTBT_MASK << IBA7220_IBC_HRTBT_SHIFT;
2709f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_devinfo(ppd->dd->pcidev, "Disabling IB%u:%u IBC loopback "
2710f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    "(normal)\n", ppd->dd->unit, ppd->port);
2711f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else
2712f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = -EINVAL;
2713f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!ret) {
2714f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(ppd->dd, kr_ibcctrl, ppd->cpspec->ibcctrl);
2715f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ddr = ppd->cpspec->ibcddrctrl & ~(IBA7220_IBC_HRTBT_MASK
2716f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					     << IBA7220_IBC_HRTBT_SHIFT);
2717f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibcddrctrl = ddr | val;
2718f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(ppd->dd, kr_ibcddrctrl,
2719f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			       ppd->cpspec->ibcddrctrl);
2720f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(ppd->dd, kr_scratch, 0);
2721f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2722f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
2723f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2724f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2725f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_update_7220_usrhead(struct qib_ctxtdata *rcd, u64 hd,
272619ede2e422496b2a064b9b22823c6afb66ff927bMike Marciniszyn				    u32 updegr, u32 egrhd, u32 npkts)
2727f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2728f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (updegr)
2729f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt);
2730eddfb675256f49d14e8c5763098afe3eb2c93701Ram Vepa	mmiowb();
2731eddfb675256f49d14e8c5763098afe3eb2c93701Ram Vepa	qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
2732eddfb675256f49d14e8c5763098afe3eb2c93701Ram Vepa	mmiowb();
2733f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2734f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2735f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u32 qib_7220_hdrqempty(struct qib_ctxtdata *rcd)
2736f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2737f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 head, tail;
2738f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2739f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	head = qib_read_ureg32(rcd->dd, ur_rcvhdrhead, rcd->ctxt);
2740f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (rcd->rcvhdrtail_kvaddr)
2741f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		tail = qib_get_rcvhdrtail(rcd);
2742f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
2743f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		tail = qib_read_ureg32(rcd->dd, ur_rcvhdrtail, rcd->ctxt);
2744f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return head == tail;
2745f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2746f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2747f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
2748f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Modify the RCVCTRL register in chip-specific way. This
2749f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * is a function because bit positions and (future) register
2750f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * location is chip-specifc, but the needed operations are
2751f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * generic. <op> is a bit-mask because we often want to
2752f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * do multiple modifications.
2753f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
2754f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void rcvctrl_7220_mod(struct qib_pportdata *ppd, unsigned int op,
2755f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			     int ctxt)
2756f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2757f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
2758f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 mask, val;
2759f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
2760f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2761f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags);
2762f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_RCVCTRL_TAILUPD_ENB)
2763f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcvctrl |= (1ULL << IBA7220_R_TAILUPD_SHIFT);
2764f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_RCVCTRL_TAILUPD_DIS)
2765f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcvctrl &= ~(1ULL << IBA7220_R_TAILUPD_SHIFT);
2766f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_RCVCTRL_PKEY_ENB)
2767f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcvctrl &= ~(1ULL << IBA7220_R_PKEY_DIS_SHIFT);
2768f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_RCVCTRL_PKEY_DIS)
2769f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcvctrl |= (1ULL << IBA7220_R_PKEY_DIS_SHIFT);
2770f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ctxt < 0)
2771f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		mask = (1ULL << dd->ctxtcnt) - 1;
2772f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
2773f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		mask = (1ULL << ctxt);
2774f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_RCVCTRL_CTXT_ENB) {
2775f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* always done for specific ctxt */
2776f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcvctrl |= (mask << SYM_LSB(RcvCtrl, PortEnable));
2777f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!(dd->flags & QIB_NODMA_RTAIL))
2778f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->rcvctrl |= 1ULL << IBA7220_R_TAILUPD_SHIFT;
2779f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* Write these registers before the context is enabled. */
2780f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg_ctxt(dd, kr_rcvhdrtailaddr, ctxt,
2781f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->rcd[ctxt]->rcvhdrqtailaddr_phys);
2782f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg_ctxt(dd, kr_rcvhdraddr, ctxt,
2783f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->rcd[ctxt]->rcvhdrq_phys);
2784f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcd[ctxt]->seq_cnt = 1;
2785f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2786f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_RCVCTRL_CTXT_DIS)
2787f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcvctrl &= ~(mask << SYM_LSB(RcvCtrl, PortEnable));
2788f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_RCVCTRL_INTRAVAIL_ENB)
2789f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcvctrl |= (mask << IBA7220_R_INTRAVAIL_SHIFT);
2790f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_RCVCTRL_INTRAVAIL_DIS)
2791f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcvctrl &= ~(mask << IBA7220_R_INTRAVAIL_SHIFT);
2792f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_rcvctrl, dd->rcvctrl);
2793f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if ((op & QIB_RCVCTRL_INTRAVAIL_ENB) && dd->rhdrhead_intr_off) {
2794f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* arm rcv interrupt */
2795f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		val = qib_read_ureg32(dd, ur_rcvhdrhead, ctxt) |
2796f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->rhdrhead_intr_off;
2797f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_ureg(dd, ur_rcvhdrhead, val, ctxt);
2798f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2799f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_RCVCTRL_CTXT_ENB) {
2800f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
2801f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * Init the context registers also; if we were
2802f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * disabled, tail and head should both be zero
2803f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * already from the enable, but since we don't
280425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		 * know, we have to do it explicitly.
2805f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
2806f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		val = qib_read_ureg32(dd, ur_rcvegrindextail, ctxt);
2807f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_ureg(dd, ur_rcvegrindexhead, val, ctxt);
2808f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2809f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		val = qib_read_ureg32(dd, ur_rcvhdrtail, ctxt);
2810f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcd[ctxt]->head = val;
2811f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* If kctxt, interrupt on next receive. */
2812f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ctxt < dd->first_user_ctxt)
2813f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			val |= dd->rhdrhead_intr_off;
2814f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_ureg(dd, ur_rcvhdrhead, val, ctxt);
2815f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2816f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_RCVCTRL_CTXT_DIS) {
2817f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ctxt >= 0) {
2818f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_write_kreg_ctxt(dd, kr_rcvhdrtailaddr, ctxt, 0);
2819f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_write_kreg_ctxt(dd, kr_rcvhdraddr, ctxt, 0);
2820f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else {
2821f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			unsigned i;
2822f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2823f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			for (i = 0; i < dd->cfgctxts; i++) {
2824f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qib_write_kreg_ctxt(dd, kr_rcvhdrtailaddr,
2825f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell						    i, 0);
2826f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qib_write_kreg_ctxt(dd, kr_rcvhdraddr, i, 0);
2827f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
2828f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
2829f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2830f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&dd->cspec->rcvmod_lock, flags);
2831f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2832f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2833f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
2834f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Modify the SENDCTRL register in chip-specific way. This
2835f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * is a function there may be multiple such registers with
2836f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * slightly different layouts. To start, we assume the
2837f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * "canonical" register layout of the first chips.
2838f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Chip requires no back-back sendctrl writes, so write
2839f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * scratch register after writing sendctrl
2840f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
2841f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void sendctrl_7220_mod(struct qib_pportdata *ppd, u32 op)
2842f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2843f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
2844f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 tmp_dd_sendctrl;
2845f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
2846f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2847f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&dd->sendctrl_lock, flags);
2848f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2849f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* First the ones that are "sticky", saved in shadow */
2850f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_SENDCTRL_CLEAR)
2851f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->sendctrl = 0;
2852f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_SENDCTRL_SEND_DIS)
2853f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->sendctrl &= ~SYM_MASK(SendCtrl, SPioEnable);
2854f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else if (op & QIB_SENDCTRL_SEND_ENB) {
2855f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->sendctrl |= SYM_MASK(SendCtrl, SPioEnable);
2856f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (dd->flags & QIB_USE_SPCL_TRIG)
2857f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->sendctrl |= SYM_MASK(SendCtrl,
2858f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell						 SSpecialTriggerEn);
2859f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2860f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_SENDCTRL_AVAIL_DIS)
2861f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->sendctrl &= ~SYM_MASK(SendCtrl, SendBufAvailUpd);
2862f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else if (op & QIB_SENDCTRL_AVAIL_ENB)
2863f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->sendctrl |= SYM_MASK(SendCtrl, SendBufAvailUpd);
2864f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2865f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_SENDCTRL_DISARM_ALL) {
2866f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u32 i, last;
2867f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2868f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		tmp_dd_sendctrl = dd->sendctrl;
2869f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
2870f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * disarm any that are not yet launched, disabling sends
2871f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * and updates until done.
2872f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
2873f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		last = dd->piobcnt2k + dd->piobcnt4k;
2874f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		tmp_dd_sendctrl &=
2875f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			~(SYM_MASK(SendCtrl, SPioEnable) |
2876f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			  SYM_MASK(SendCtrl, SendBufAvailUpd));
2877f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		for (i = 0; i < last; i++) {
2878f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_write_kreg(dd, kr_sendctrl,
2879f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				       tmp_dd_sendctrl |
2880f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				       SYM_MASK(SendCtrl, Disarm) | i);
2881f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_write_kreg(dd, kr_scratch, 0);
2882f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
2883f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2884f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2885f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	tmp_dd_sendctrl = dd->sendctrl;
2886f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2887f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_SENDCTRL_FLUSH)
2888f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		tmp_dd_sendctrl |= SYM_MASK(SendCtrl, Abort);
2889f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_SENDCTRL_DISARM)
2890f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		tmp_dd_sendctrl |= SYM_MASK(SendCtrl, Disarm) |
2891f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			((op & QIB_7220_SendCtrl_DisarmPIOBuf_RMASK) <<
2892f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 SYM_LSB(SendCtrl, DisarmPIOBuf));
2893f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if ((op & QIB_SENDCTRL_AVAIL_BLIP) &&
2894f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	    (dd->sendctrl & SYM_MASK(SendCtrl, SendBufAvailUpd)))
2895f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		tmp_dd_sendctrl &= ~SYM_MASK(SendCtrl, SendBufAvailUpd);
2896f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2897f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_sendctrl, tmp_dd_sendctrl);
2898f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_scratch, 0);
2899f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2900f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_SENDCTRL_AVAIL_BLIP) {
2901f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_sendctrl, dd->sendctrl);
2902f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_scratch, 0);
2903f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2904f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2905f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&dd->sendctrl_lock, flags);
2906f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2907f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (op & QIB_SENDCTRL_FLUSH) {
2908f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u32 v;
2909f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
2910f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * ensure writes have hit chip, then do a few
2911f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * more reads, to allow DMA of pioavail registers
2912f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * to occur, so in-memory copy is in sync with
2913f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * the chip.  Not always safe to sleep.
2914f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
2915f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		v = qib_read_kreg32(dd, kr_scratch);
2916f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_scratch, v);
2917f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		v = qib_read_kreg32(dd, kr_scratch);
2918f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_scratch, v);
2919f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_read_kreg32(dd, kr_scratch);
2920f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2921f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
2922f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2923f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
2924f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_portcntr_7220 - read a per-port counter
2925f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dd: the qlogic_ib device
2926f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @creg: the counter to snapshot
2927f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
2928f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u64 qib_portcntr_7220(struct qib_pportdata *ppd, u32 reg)
2929f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
2930f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 ret = 0ULL;
2931f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
2932f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u16 creg;
2933f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* 0xffff for unimplemented or synthesized counters */
2934f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	static const u16 xlator[] = {
2935f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_PKTSEND] = cr_pktsend,
2936f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_WORDSEND] = cr_wordsend,
2937f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_PSXMITDATA] = cr_psxmitdatacount,
2938f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_PSXMITPKTS] = cr_psxmitpktscount,
2939f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_PSXMITWAIT] = cr_psxmitwaitcount,
2940f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_SENDSTALL] = cr_sendstall,
2941f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_PKTRCV] = cr_pktrcv,
2942f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_PSRCVDATA] = cr_psrcvdatacount,
2943f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_PSRCVPKTS] = cr_psrcvpktscount,
2944f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_RCVEBP] = cr_rcvebp,
2945f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_RCVOVFL] = cr_rcvovfl,
2946f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_WORDRCV] = cr_wordrcv,
2947f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_RXDROPPKT] = cr_rxdroppkt,
2948f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_RXLOCALPHYERR] = cr_rxotherlocalphyerr,
2949f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_RXVLERR] = cr_rxvlerr,
2950f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_ERRICRC] = cr_erricrc,
2951f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_ERRVCRC] = cr_errvcrc,
2952f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_ERRLPCRC] = cr_errlpcrc,
2953f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_BADFORMAT] = cr_badformat,
2954f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_ERR_RLEN] = cr_err_rlen,
2955f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_IBSYMBOLERR] = cr_ibsymbolerr,
2956f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_INVALIDRLEN] = cr_invalidrlen,
2957f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_UNSUPVL] = cr_txunsupvl,
2958f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_EXCESSBUFOVFL] = cr_excessbufferovfl,
2959f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_ERRLINK] = cr_errlink,
2960f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_IBLINKDOWN] = cr_iblinkdown,
2961f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_IBLINKERRRECOV] = cr_iblinkerrrecov,
2962f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_LLI] = cr_locallinkintegrityerr,
2963f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_PSINTERVAL] = cr_psinterval,
2964f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_PSSTART] = cr_psstart,
2965f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_PSSTAT] = cr_psstat,
2966f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_VL15PKTDROP] = cr_vl15droppedpkt,
2967f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_ERRPKEY] = cr_errpkey,
2968f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		[QIBPORTCNTR_KHDROVFL] = 0xffff,
2969f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	};
2970f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2971f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (reg >= ARRAY_SIZE(xlator)) {
2972f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_devinfo(ppd->dd->pcidev,
2973f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 "Unimplemented portcounter %u\n", reg);
2974f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2975f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2976f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	creg = xlator[reg];
2977f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2978f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (reg == QIBPORTCNTR_KHDROVFL) {
2979f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		int i;
2980f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2981f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* sum over all kernel contexts */
2982f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		for (i = 0; i < dd->first_user_ctxt; i++)
2983f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret += read_7220_creg32(dd, cr_portovfl + i);
2984f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
2985f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (creg == 0xffff)
2986f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
2987f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
2988f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
2989f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * only fast incrementing counters are 64bit; use 32 bit reads to
2990f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * avoid two independent reads when on opteron
2991f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
2992f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if ((creg == cr_wordsend || creg == cr_wordrcv ||
2993f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	     creg == cr_pktsend || creg == cr_pktrcv))
2994f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = read_7220_creg(dd, creg);
2995f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
2996f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = read_7220_creg32(dd, creg);
2997f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (creg == cr_ibsymbolerr) {
2998f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (dd->pport->cpspec->ibdeltainprog)
2999f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret -= ret - ppd->cpspec->ibsymsnap;
3000f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret -= dd->pport->cpspec->ibsymdelta;
3001f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else if (creg == cr_iblinkerrrecov) {
3002f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (dd->pport->cpspec->ibdeltainprog)
3003f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret -= ret - ppd->cpspec->iblnkerrsnap;
3004f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret -= dd->pport->cpspec->iblnkerrdelta;
3005f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3006f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbelldone:
3007f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
3008f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3009f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3010f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3011f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Device counter names (not port-specific), one line per stat,
3012f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * single string.  Used by utilities like ipathstats to print the stats
3013f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * in a way which works for different versions of drivers, without changing
3014f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * the utility.  Names need to be 12 chars or less (w/o newline), for proper
3015f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * display by utility.
3016f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Non-error counters are first.
3017f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Start of "error" conters is indicated by a leading "E " on the first
3018f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * "error" counter, and doesn't count in label length.
3019f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * The EgrOvfl list needs to be last so we truncate them at the configured
3020f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * context count for the device.
3021f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * cntr7220indices contains the corresponding register indices.
3022f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3023f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic const char cntr7220names[] =
3024f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Interrupts\n"
3025f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"HostBusStall\n"
3026f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"E RxTIDFull\n"
3027f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxTIDInvalid\n"
3028f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctxt0EgrOvfl\n"
3029f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctxt1EgrOvfl\n"
3030f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctxt2EgrOvfl\n"
3031f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctxt3EgrOvfl\n"
3032f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctxt4EgrOvfl\n"
3033f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctxt5EgrOvfl\n"
3034f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctxt6EgrOvfl\n"
3035f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctxt7EgrOvfl\n"
3036f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctxt8EgrOvfl\n"
3037f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctxt9EgrOvfl\n"
3038f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctx10EgrOvfl\n"
3039f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctx11EgrOvfl\n"
3040f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctx12EgrOvfl\n"
3041f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctx13EgrOvfl\n"
3042f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctx14EgrOvfl\n"
3043f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctx15EgrOvfl\n"
3044f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"Ctx16EgrOvfl\n";
3045f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3046f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic const size_t cntr7220indices[] = {
3047f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_lbint,
3048f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_lbflowstall,
3049f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_errtidfull,
3050f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_errtidvalid,
3051f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 0,
3052f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 1,
3053f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 2,
3054f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 3,
3055f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 4,
3056f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 5,
3057f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 6,
3058f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 7,
3059f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 8,
3060f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 9,
3061f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 10,
3062f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 11,
3063f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 12,
3064f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 13,
3065f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 14,
3066f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 15,
3067f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_portovfl + 16,
3068f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell};
3069f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3070f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3071f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * same as cntr7220names and cntr7220indices, but for port-specific counters.
3072f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * portcntr7220indices is somewhat complicated by some registers needing
3073f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * adjustments of various kinds, and those are ORed with _PORT_VIRT_FLAG
3074f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3075f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic const char portcntr7220names[] =
3076f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"TxPkt\n"
3077f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"TxFlowPkt\n"
3078f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"TxWords\n"
3079f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxPkt\n"
3080f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxFlowPkt\n"
3081f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxWords\n"
3082f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"TxFlowStall\n"
3083f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"TxDmaDesc\n"  /* 7220 and 7322-only */
3084f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"E RxDlidFltr\n"  /* 7220 and 7322-only */
3085f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"IBStatusChng\n"
3086f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"IBLinkDown\n"
3087f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"IBLnkRecov\n"
3088f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"IBRxLinkErr\n"
3089f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"IBSymbolErr\n"
3090f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxLLIErr\n"
3091f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxBadFormat\n"
3092f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxBadLen\n"
3093f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxBufOvrfl\n"
3094f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxEBP\n"
3095f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxFlowCtlErr\n"
3096f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxICRCerr\n"
3097f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxLPCRCerr\n"
3098f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxVCRCerr\n"
3099f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxInvalLen\n"
3100f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxInvalPKey\n"
3101f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxPktDropped\n"
3102f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"TxBadLength\n"
3103f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"TxDropped\n"
3104f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"TxInvalLen\n"
3105f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"TxUnderrun\n"
3106f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"TxUnsupVL\n"
3107f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxLclPhyErr\n" /* 7220 and 7322-only */
3108f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxVL15Drop\n" /* 7220 and 7322-only */
3109f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"RxVlErr\n" /* 7220 and 7322-only */
3110f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	"XcessBufOvfl\n" /* 7220 and 7322-only */
3111f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	;
3112f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3113f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define _PORT_VIRT_FLAG 0x8000 /* "virtual", need adjustments */
3114f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic const size_t portcntr7220indices[] = {
3115f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_PKTSEND | _PORT_VIRT_FLAG,
3116f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_pktsendflow,
3117f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_WORDSEND | _PORT_VIRT_FLAG,
3118f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_PKTRCV | _PORT_VIRT_FLAG,
3119f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_pktrcvflowctrl,
3120f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_WORDRCV | _PORT_VIRT_FLAG,
3121f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_SENDSTALL | _PORT_VIRT_FLAG,
3122f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_txsdmadesc,
3123f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_rxdlidfltr,
3124f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_ibstatuschange,
3125f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_IBLINKDOWN | _PORT_VIRT_FLAG,
3126f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_IBLINKERRRECOV | _PORT_VIRT_FLAG,
3127f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_ERRLINK | _PORT_VIRT_FLAG,
3128f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_IBSYMBOLERR | _PORT_VIRT_FLAG,
3129f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_LLI | _PORT_VIRT_FLAG,
3130f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_BADFORMAT | _PORT_VIRT_FLAG,
3131f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_ERR_RLEN | _PORT_VIRT_FLAG,
3132f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_RCVOVFL | _PORT_VIRT_FLAG,
3133f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_RCVEBP | _PORT_VIRT_FLAG,
3134f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_rcvflowctrl_err,
3135f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_ERRICRC | _PORT_VIRT_FLAG,
3136f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_ERRLPCRC | _PORT_VIRT_FLAG,
3137f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_ERRVCRC | _PORT_VIRT_FLAG,
3138f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_INVALIDRLEN | _PORT_VIRT_FLAG,
3139f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_ERRPKEY | _PORT_VIRT_FLAG,
3140f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_RXDROPPKT | _PORT_VIRT_FLAG,
3141f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_invalidslen,
3142f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_senddropped,
3143f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_errslen,
3144f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_sendunderrun,
3145f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cr_txunsupvl,
3146f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_RXLOCALPHYERR | _PORT_VIRT_FLAG,
3147f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_VL15PKTDROP | _PORT_VIRT_FLAG,
3148f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_RXVLERR | _PORT_VIRT_FLAG,
3149f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	QIBPORTCNTR_EXCESSBUFOVFL | _PORT_VIRT_FLAG,
3150f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell};
3151f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3152f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* do all the setup to make the counter reads efficient later */
3153f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void init_7220_cntrnames(struct qib_devdata *dd)
3154f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3155f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int i, j = 0;
3156f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	char *s;
3157f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3158f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (i = 0, s = (char *)cntr7220names; s && j <= dd->cfgctxts;
3159f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	     i++) {
3160f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* we always have at least one counter before the egrovfl */
3161f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!j && !strncmp("Ctxt0EgrOvfl", s + 1, 12))
3162f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			j = 1;
3163f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		s = strchr(s + 1, '\n');
3164f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (s && j)
3165f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			j++;
3166f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3167f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->ncntrs = i;
3168f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!s)
3169f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* full list; size is without terminating null */
3170f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->cntrnamelen = sizeof(cntr7220names) - 1;
3171f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
3172f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->cntrnamelen = 1 + s - cntr7220names;
3173f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->cntrs = kmalloc(dd->cspec->ncntrs
3174f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		* sizeof(u64), GFP_KERNEL);
3175f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!dd->cspec->cntrs)
3176f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "Failed allocation for counters\n");
3177f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3178f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (i = 0, s = (char *)portcntr7220names; s; i++)
3179f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		s = strchr(s + 1, '\n');
3180f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->nportcntrs = i - 1;
3181f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->portcntrnamelen = sizeof(portcntr7220names) - 1;
3182f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->portcntrs = kmalloc(dd->cspec->nportcntrs
3183f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		* sizeof(u64), GFP_KERNEL);
3184f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!dd->cspec->portcntrs)
3185f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "Failed allocation for portcounters\n");
3186f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3187f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3188f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u32 qib_read_7220cntrs(struct qib_devdata *dd, loff_t pos, char **namep,
3189f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			      u64 **cntrp)
3190f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3191f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 ret;
3192f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3193f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!dd->cspec->cntrs) {
3194f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = 0;
3195f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
3196f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3197f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3198f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (namep) {
3199f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		*namep = (char *)cntr7220names;
3200f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = dd->cspec->cntrnamelen;
3201f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (pos >= ret)
3202f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = 0; /* final read after getting everything */
3203f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else {
3204f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u64 *cntr = dd->cspec->cntrs;
3205f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		int i;
3206f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3207f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = dd->cspec->ncntrs * sizeof(u64);
3208f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!cntr || pos >= ret) {
3209f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/* everything read, or couldn't get memory */
3210f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = 0;
3211f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto done;
3212f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
3213f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3214f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		*cntrp = cntr;
3215f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		for (i = 0; i < dd->cspec->ncntrs; i++)
3216f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			*cntr++ = read_7220_creg32(dd, cntr7220indices[i]);
3217f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3218f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbelldone:
3219f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
3220f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3221f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3222f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u32 qib_read_7220portcntrs(struct qib_devdata *dd, loff_t pos, u32 port,
3223f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				  char **namep, u64 **cntrp)
3224f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3225f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 ret;
3226f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3227f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!dd->cspec->portcntrs) {
3228f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = 0;
3229f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
3230f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3231f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (namep) {
3232f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		*namep = (char *)portcntr7220names;
3233f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = dd->cspec->portcntrnamelen;
3234f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (pos >= ret)
3235f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = 0; /* final read after getting everything */
3236f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else {
3237f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u64 *cntr = dd->cspec->portcntrs;
3238f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		struct qib_pportdata *ppd = &dd->pport[port];
3239f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		int i;
3240f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3241f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = dd->cspec->nportcntrs * sizeof(u64);
3242f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!cntr || pos >= ret) {
3243f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/* everything read, or couldn't get memory */
3244f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = 0;
3245f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto done;
3246f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
3247f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		*cntrp = cntr;
3248f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		for (i = 0; i < dd->cspec->nportcntrs; i++) {
3249f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (portcntr7220indices[i] & _PORT_VIRT_FLAG)
3250f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				*cntr++ = qib_portcntr_7220(ppd,
3251f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					portcntr7220indices[i] &
3252f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					~_PORT_VIRT_FLAG);
3253f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			else
3254f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				*cntr++ = read_7220_creg32(dd,
3255f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					   portcntr7220indices[i]);
3256f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
3257f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3258f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbelldone:
3259f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
3260f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3261f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3262f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
3263f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_get_7220_faststats - get word counters from chip before they overflow
3264f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @opaque - contains a pointer to the qlogic_ib device qib_devdata
3265f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
3266f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This needs more work; in particular, decision on whether we really
3267f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * need traffic_wds done the way it is
3268f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * called from add_timer
3269f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3270f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_get_7220_faststats(unsigned long opaque)
3271f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3272f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = (struct qib_devdata *) opaque;
3273f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_pportdata *ppd = dd->pport;
3274f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
3275f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 traffic_wds;
3276f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3277f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
3278f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * don't access the chip while running diags, or memory diags can
3279f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * fail
3280f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
3281f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!(dd->flags & QIB_INITTED) || dd->diag_client)
3282f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* but re-arm the timer, for diags case; won't hurt other */
3283f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
3284f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3285f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
3286f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * We now try to maintain an activity timer, based on traffic
3287f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * exceeding a threshold, so we need to check the word-counts
3288f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * even if they are 64-bit.
3289f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
3290f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	traffic_wds = qib_portcntr_7220(ppd, cr_wordsend) +
3291f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_portcntr_7220(ppd, cr_wordrcv);
3292f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&dd->eep_st_lock, flags);
3293f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	traffic_wds -= dd->traffic_wds;
3294f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->traffic_wds += traffic_wds;
3295f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (traffic_wds  >= QIB_TRAFFIC_ACTIVE_THRESHOLD)
3296f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		atomic_add(5, &dd->active_time); /* S/B #define */
3297f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&dd->eep_st_lock, flags);
3298f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbelldone:
3299f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	mod_timer(&dd->stats_timer, jiffies + HZ * ACTIVITY_TIMER);
3300f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3301f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3302f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3303f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * If we are using MSI, try to fallback to INTx.
3304f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3305f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_7220_intr_fallback(struct qib_devdata *dd)
3306f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3307f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!dd->msi_lo)
3308f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		return 0;
3309f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3310f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_devinfo(dd->pcidev, "MSI interrupt not detected,"
3311f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 " trying INTx interrupts\n");
3312f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_7220_free_irq(dd);
3313f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_enable_intx(dd->pcidev);
3314f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
3315f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Some newer kernels require free_irq before disable_msi,
3316f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * and irq can be changed during disable and INTx enable
3317f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * and we need to therefore use the pcidev->irq value,
3318f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * not our saved MSI value.
3319f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
3320f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->irq = dd->pcidev->irq;
3321f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_setup_7220_interrupt(dd);
3322f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return 1;
3323f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3324f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3325f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3326f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Reset the XGXS (between serdes and IBC).  Slightly less intrusive
3327f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * than resetting the IBC or external link state, and useful in some
3328f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * cases to cause some retraining.  To do this right, we reset IBC
3329f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * as well.
3330f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3331f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_xgxs_reset(struct qib_pportdata *ppd)
3332f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3333f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 val, prev_val;
3334f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
3335f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3336f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	prev_val = qib_read_kreg64(dd, kr_xgxs_cfg);
3337f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	val = prev_val | QLOGIC_IB_XGXS_RESET;
3338f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	prev_val &= ~QLOGIC_IB_XGXS_RESET; /* be sure */
3339f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_control,
3340f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		       dd->control & ~QLOGIC_IB_C_LINKENABLE);
3341f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_xgxs_cfg, val);
3342f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_read_kreg32(dd, kr_scratch);
3343f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_xgxs_cfg, prev_val);
3344f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_control, dd->control);
3345f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3346f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3347f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3348f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * For this chip, we want to use the same buffer every time
3349f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * when we are trying to bring the link up (they are always VL15
3350f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * packets).  At that link state the packet should always go out immediately
3351f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * (or at least be discarded at the tx interface if the link is down).
3352f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * If it doesn't, and the buffer isn't available, that means some other
3353f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * sender has gotten ahead of us, and is preventing our packet from going
3354f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * out.  In that case, we flush all packets, and try again.  If that still
3355f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * fails, we fail the request, and hope things work the next time around.
3356f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
3357f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * We don't need very complicated heuristics on whether the packet had
3358f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * time to go out or not, since even at SDR 1X, it goes out in very short
3359f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * time periods, covered by the chip reads done here and as part of the
3360f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * flush.
3361f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3362f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u32 __iomem *get_7220_link_buf(struct qib_pportdata *ppd, u32 *bnum)
3363f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3364f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 __iomem *buf;
3365f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 lbuf = ppd->dd->cspec->lastbuf_for_pio;
3366f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int do_cleanup;
3367f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
3368f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3369f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
3370f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * always blip to get avail list updated, since it's almost
3371f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * always needed, and is fairly cheap.
3372f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
3373f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	sendctrl_7220_mod(ppd->dd->pport, QIB_SENDCTRL_AVAIL_BLIP);
3374f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_read_kreg64(ppd->dd, kr_scratch); /* extra chip flush */
3375f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	buf = qib_getsendbuf_range(ppd->dd, bnum, lbuf, lbuf);
3376f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (buf)
3377f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
3378f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3379f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&ppd->sdma_lock, flags);
3380f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ppd->sdma_state.current_state == qib_sdma_state_s20_idle &&
3381f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	    ppd->sdma_state.current_state != qib_sdma_state_s00_hw_down) {
3382f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		__qib_sdma_process_event(ppd, qib_sdma_event_e00_go_hw_down);
3383f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		do_cleanup = 0;
3384f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else {
3385f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		do_cleanup = 1;
3386f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_7220_sdma_hw_clean_up(ppd);
3387f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3388f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&ppd->sdma_lock, flags);
3389f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3390f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (do_cleanup) {
3391f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_read_kreg64(ppd->dd, kr_scratch); /* extra chip flush */
3392f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		buf = qib_getsendbuf_range(ppd->dd, bnum, lbuf, lbuf);
3393f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3394f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbelldone:
3395f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return buf;
3396f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3397f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3398f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3399f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This code for non-IBTA-compliant IB speed negotiation is only known to
3400f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * work for the SDR to DDR transition, and only between an HCA and a switch
3401f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * with recent firmware.  It is based on observed heuristics, rather than
3402f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * actual knowledge of the non-compliant speed negotiation.
3403f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * It has a number of hard-coded fields, since the hope is to rewrite this
3404f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * when a spec is available on how the negoation is intended to work.
3405f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3406f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void autoneg_7220_sendpkt(struct qib_pportdata *ppd, u32 *hdr,
3407f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				 u32 dcnt, u32 *data)
3408f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3409f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int i;
3410f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 pbc;
3411f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 __iomem *piobuf;
3412f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 pnum;
3413f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
3414f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3415f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	i = 0;
3416f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	pbc = 7 + dcnt + 1; /* 7 dword header, dword data, icrc */
3417f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	pbc |= PBC_7220_VL15_SEND;
3418f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	while (!(piobuf = get_7220_link_buf(ppd, &pnum))) {
3419f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (i++ > 5)
3420f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			return;
3421f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		udelay(2);
3422f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3423f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	sendctrl_7220_mod(dd->pport, QIB_SENDCTRL_DISARM_BUF(pnum));
3424f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	writeq(pbc, piobuf);
3425f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_flush_wc();
3426f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_pio_copy(piobuf + 2, hdr, 7);
3427f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_pio_copy(piobuf + 9, data, dcnt);
3428f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->flags & QIB_USE_SPCL_TRIG) {
3429f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u32 spcl_off = (pnum >= dd->piobcnt2k) ? 2047 : 1023;
3430f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3431f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_flush_wc();
3432f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		__raw_writel(0xaebecede, piobuf + spcl_off);
3433f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3434f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_flush_wc();
3435f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_sendbuf_done(dd, pnum);
3436f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3437f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3438f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3439f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * _start packet gets sent twice at start, _done gets sent twice at end
3440f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3441f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void autoneg_7220_send(struct qib_pportdata *ppd, int which)
3442f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3443f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
3444f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	static u32 swapped;
3445f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 dw, i, hcnt, dcnt, *data;
3446f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	static u32 hdr[7] = { 0xf002ffff, 0x48ffff, 0x6400abba };
3447f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	static u32 madpayload_start[0x40] = {
3448f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		0x1810103, 0x1, 0x0, 0x0, 0x2c90000, 0x2c9, 0x0, 0x0,
3449f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		0xffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3450f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		0x1, 0x1388, 0x15e, 0x1, /* rest 0's */
3451f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		};
3452f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	static u32 madpayload_done[0x40] = {
3453f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		0x1810103, 0x1, 0x0, 0x0, 0x2c90000, 0x2c9, 0x0, 0x0,
3454f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		0xffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3455f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		0x40000001, 0x1388, 0x15e, /* rest 0's */
3456f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		};
3457f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3458f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dcnt = ARRAY_SIZE(madpayload_start);
3459f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	hcnt = ARRAY_SIZE(hdr);
3460f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!swapped) {
3461f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* for maintainability, do it at runtime */
3462f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		for (i = 0; i < hcnt; i++) {
3463f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dw = (__force u32) cpu_to_be32(hdr[i]);
3464f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			hdr[i] = dw;
3465f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
3466f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		for (i = 0; i < dcnt; i++) {
3467f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dw = (__force u32) cpu_to_be32(madpayload_start[i]);
3468f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			madpayload_start[i] = dw;
3469f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dw = (__force u32) cpu_to_be32(madpayload_done[i]);
3470f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			madpayload_done[i] = dw;
3471f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
3472f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		swapped = 1;
3473f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3474f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3475f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	data = which ? madpayload_done : madpayload_start;
3476f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3477f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	autoneg_7220_sendpkt(ppd, hdr, dcnt, data);
3478f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_read_kreg64(dd, kr_scratch);
3479f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	udelay(2);
3480f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	autoneg_7220_sendpkt(ppd, hdr, dcnt, data);
3481f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_read_kreg64(dd, kr_scratch);
3482f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	udelay(2);
3483f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3484f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3485f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3486f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Do the absolute minimum to cause an IB speed change, and make it
3487f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * ready, but don't actually trigger the change.   The caller will
3488f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * do that when ready (if link is in Polling training state, it will
3489f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * happen immediately, otherwise when link next goes down)
3490f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
3491f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This routine should only be used as part of the DDR autonegotation
3492f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * code for devices that are not compliant with IB 1.2 (or code that
3493f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * fixes things up for same).
3494f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
3495f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * When link has gone down, and autoneg enabled, or autoneg has
3496f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * failed and we give up until next time we set both speeds, and
3497f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * then we want IBTA enabled as well as "use max enabled speed.
3498f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3499f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void set_7220_ibspeed_fast(struct qib_pportdata *ppd, u32 speed)
3500f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3501f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->cpspec->ibcddrctrl &= ~(IBA7220_IBC_SPEED_AUTONEG_MASK |
3502f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		IBA7220_IBC_IBTA_1_2_MASK);
3503f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3504f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (speed == (QIB_IB_SDR | QIB_IB_DDR))
3505f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibcddrctrl |= IBA7220_IBC_SPEED_AUTONEG_MASK |
3506f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			IBA7220_IBC_IBTA_1_2_MASK;
3507f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else
3508f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibcddrctrl |= speed == QIB_IB_DDR ?
3509f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			IBA7220_IBC_SPEED_DDR : IBA7220_IBC_SPEED_SDR;
3510f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3511f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(ppd->dd, kr_ibcddrctrl, ppd->cpspec->ibcddrctrl);
3512f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(ppd->dd, kr_scratch, 0);
3513f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3514f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3515f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3516f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This routine is only used when we are not talking to another
3517f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * IB 1.2-compliant device that we think can do DDR.
3518f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * (This includes all existing switch chips as of Oct 2007.)
3519f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * 1.2-compliant devices go directly to DDR prior to reaching INIT
3520f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3521f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void try_7220_autoneg(struct qib_pportdata *ppd)
3522f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3523f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
3524f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3525f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
3526f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Required for older non-IB1.2 DDR switches.  Newer
3527f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * non-IB-compliant switches don't need it, but so far,
3528f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * aren't bothered by it either.  "Magic constant"
3529f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
3530f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(ppd->dd, kr_ncmodectrl, 0x3b9dc07);
3531f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3532f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&ppd->lflags_lock, flags);
3533f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->lflags |= QIBL_IB_AUTONEG_INPROG;
3534f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&ppd->lflags_lock, flags);
3535f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	autoneg_7220_send(ppd, 0);
3536f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	set_7220_ibspeed_fast(ppd, QIB_IB_DDR);
3537f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3538f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	toggle_7220_rclkrls(ppd->dd);
3539f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* 2 msec is minimum length of a poll cycle */
3540f06267104dd9112f11586830d22501d0e26245eaTejun Heo	queue_delayed_work(ib_wq, &ppd->cpspec->autoneg_work,
3541f06267104dd9112f11586830d22501d0e26245eaTejun Heo			   msecs_to_jiffies(2));
3542f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3543f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3544f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3545f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Handle the empirically determined mechanism for auto-negotiation
3546f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * of DDR speed with switches.
3547f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3548f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void autoneg_7220_work(struct work_struct *work)
3549f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3550f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_pportdata *ppd;
3551f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd;
3552f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 startms;
3553f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 i;
3554f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
3555f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3556f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd = &container_of(work, struct qib_chippport_specific,
3557f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    autoneg_work.work)->pportdata;
3558f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd = ppd->dd;
3559f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3560f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	startms = jiffies_to_msecs(jiffies);
3561f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3562f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
3563f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Busy wait for this first part, it should be at most a
3564f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * few hundred usec, since we scheduled ourselves for 2msec.
3565f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
3566f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (i = 0; i < 25; i++) {
3567f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (SYM_FIELD(ppd->lastibcstat, IBCStatus, LinkTrainingState)
3568f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		     == IB_7220_LT_STATE_POLLQUIET) {
3569f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_set_linkstate(ppd, QIB_IB_LINKDOWN_DISABLE);
3570f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			break;
3571f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
3572f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		udelay(100);
3573f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3574f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3575f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG))
3576f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done; /* we got there early or told to stop */
3577f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3578f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* we expect this to timeout */
3579f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (wait_event_timeout(ppd->cpspec->autoneg_wait,
3580f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			       !(ppd->lflags & QIBL_IB_AUTONEG_INPROG),
3581f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			       msecs_to_jiffies(90)))
3582f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
3583f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3584f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	toggle_7220_rclkrls(dd);
3585f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3586f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* we expect this to timeout */
3587f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (wait_event_timeout(ppd->cpspec->autoneg_wait,
3588f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			       !(ppd->lflags & QIBL_IB_AUTONEG_INPROG),
3589f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			       msecs_to_jiffies(1700)))
3590f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto done;
3591f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3592f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	set_7220_ibspeed_fast(ppd, QIB_IB_SDR);
3593f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	toggle_7220_rclkrls(dd);
3594f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3595f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
3596f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Wait up to 250 msec for link to train and get to INIT at DDR;
3597f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * this should terminate early.
3598f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
3599f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	wait_event_timeout(ppd->cpspec->autoneg_wait,
3600f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		!(ppd->lflags & QIBL_IB_AUTONEG_INPROG),
3601f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		msecs_to_jiffies(250));
3602f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbelldone:
3603f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ppd->lflags & QIBL_IB_AUTONEG_INPROG) {
3604f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock_irqsave(&ppd->lflags_lock, flags);
3605f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->lflags &= ~QIBL_IB_AUTONEG_INPROG;
3606f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (dd->cspec->autoneg_tries == AUTONEG_TRIES) {
3607f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->lflags |= QIBL_IB_AUTONEG_FAILED;
3608f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->cspec->autoneg_tries = 0;
3609f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
3610f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
3611f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		set_7220_ibspeed_fast(ppd, ppd->link_speed_enabled);
3612f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3613f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3614f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3615f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u32 qib_7220_iblink_state(u64 ibcs)
3616f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3617f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 state = (u32)SYM_FIELD(ibcs, IBCStatus, LinkState);
3618f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3619f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	switch (state) {
3620f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_7220_L_STATE_INIT:
3621f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		state = IB_PORT_INIT;
3622f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
3623f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_7220_L_STATE_ARM:
3624f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		state = IB_PORT_ARMED;
3625f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
3626f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_7220_L_STATE_ACTIVE:
3627f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* fall through */
3628f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_7220_L_STATE_ACT_DEFER:
3629f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		state = IB_PORT_ACTIVE;
3630f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
3631f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	default: /* fall through */
3632f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case IB_7220_L_STATE_DOWN:
3633f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		state = IB_PORT_DOWN;
3634f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
3635f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3636f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return state;
3637f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3638f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3639f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* returns the IBTA port state, rather than the IBC link training state */
3640f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u8 qib_7220_phys_portstate(u64 ibcs)
3641f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3642f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u8 state = (u8)SYM_FIELD(ibcs, IBCStatus, LinkTrainingState);
3643f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return qib_7220_physportstate[state];
3644f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3645f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3646f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_7220_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
3647f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3648f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int ret = 0, symadj = 0;
3649f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
3650f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
3651f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3652f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&ppd->lflags_lock, flags);
3653f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->lflags &= ~QIBL_IB_FORCE_NOTIFY;
3654f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&ppd->lflags_lock, flags);
3655f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3656f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!ibup) {
3657f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
3658f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * When the link goes down we don't want AEQ running, so it
3659f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * won't interfere with IBC training, etc., and we need
3660f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * to go back to the static SerDes preset values.
3661f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
3662f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!(ppd->lflags & (QIBL_IB_AUTONEG_FAILED |
3663f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				     QIBL_IB_AUTONEG_INPROG)))
3664f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			set_7220_ibspeed_fast(ppd, ppd->link_speed_enabled);
3665f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) {
3666f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_sd7220_presets(dd);
3667f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_cancel_sends(ppd); /* initial disarm, etc. */
3668f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_lock_irqsave(&ppd->sdma_lock, flags);
3669f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (__qib_sdma_running(ppd))
3670f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				__qib_sdma_process_event(ppd,
3671f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					qib_sdma_event_e70_go_idle);
3672f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_unlock_irqrestore(&ppd->sdma_lock, flags);
3673f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
3674f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* this might better in qib_sd7220_presets() */
3675f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		set_7220_relock_poll(dd, ibup);
3676f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else {
3677f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (qib_compat_ddr_negotiate &&
3678f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    !(ppd->lflags & (QIBL_IB_AUTONEG_FAILED |
3679f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				     QIBL_IB_AUTONEG_INPROG)) &&
3680f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    ppd->link_speed_active == QIB_IB_SDR &&
3681f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    (ppd->link_speed_enabled & (QIB_IB_DDR | QIB_IB_SDR)) ==
3682f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    (QIB_IB_DDR | QIB_IB_SDR) &&
3683f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    dd->cspec->autoneg_tries < AUTONEG_TRIES) {
3684f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/* we are SDR, and DDR auto-negotiation enabled */
3685f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			++dd->cspec->autoneg_tries;
3686f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (!ppd->cpspec->ibdeltainprog) {
3687f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->cpspec->ibdeltainprog = 1;
3688f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->cpspec->ibsymsnap = read_7220_creg32(dd,
3689f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					cr_ibsymbolerr);
3690f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->cpspec->iblnkerrsnap = read_7220_creg32(dd,
3691f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					cr_iblinkerrrecov);
3692f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
3693f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			try_7220_autoneg(ppd);
3694f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = 1; /* no other IB status change processing */
3695f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else if ((ppd->lflags & QIBL_IB_AUTONEG_INPROG) &&
3696f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			   ppd->link_speed_active == QIB_IB_SDR) {
3697f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			autoneg_7220_send(ppd, 1);
3698f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			set_7220_ibspeed_fast(ppd, QIB_IB_DDR);
3699f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			udelay(2);
3700f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			toggle_7220_rclkrls(dd);
3701f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ret = 1; /* no other IB status change processing */
3702f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else {
3703f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if ((ppd->lflags & QIBL_IB_AUTONEG_INPROG) &&
3704f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    (ppd->link_speed_active & QIB_IB_DDR)) {
3705f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				spin_lock_irqsave(&ppd->lflags_lock, flags);
3706f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->lflags &= ~(QIBL_IB_AUTONEG_INPROG |
3707f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell						 QIBL_IB_AUTONEG_FAILED);
3708f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				spin_unlock_irqrestore(&ppd->lflags_lock,
3709f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell						       flags);
3710f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				dd->cspec->autoneg_tries = 0;
3711f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				/* re-enable SDR, for next link down */
3712f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				set_7220_ibspeed_fast(ppd,
3713f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell						      ppd->link_speed_enabled);
3714f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				wake_up(&ppd->cpspec->autoneg_wait);
3715f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				symadj = 1;
3716f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			} else if (ppd->lflags & QIBL_IB_AUTONEG_FAILED) {
3717f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				/*
3718f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				 * Clear autoneg failure flag, and do setup
3719f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				 * so we'll try next time link goes down and
3720f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				 * back to INIT (possibly connected to a
3721f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				 * different device).
3722f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				 */
3723f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				spin_lock_irqsave(&ppd->lflags_lock, flags);
3724f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->lflags &= ~QIBL_IB_AUTONEG_FAILED;
3725f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				spin_unlock_irqrestore(&ppd->lflags_lock,
3726f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell						       flags);
3727f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->cpspec->ibcddrctrl |=
3728f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					IBA7220_IBC_IBTA_1_2_MASK;
3729f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qib_write_kreg(dd, kr_ncmodectrl, 0);
3730f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				symadj = 1;
3731f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
3732f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
3733f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3734f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG))
3735f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			symadj = 1;
3736f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3737f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!ret) {
3738f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->delay_mult = rate_to_delay
3739f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    [(ibcs >> IBA7220_LINKSPEED_SHIFT) & 1]
3740f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    [(ibcs >> IBA7220_LINKWIDTH_SHIFT) & 1];
3741f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3742f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			set_7220_relock_poll(dd, ibup);
3743f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_lock_irqsave(&ppd->sdma_lock, flags);
3744f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/*
3745f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * Unlike 7322, the 7220 needs this, due to lack of
3746f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * interrupt in some cases when we have sdma active
3747f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 * when the link goes down.
3748f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 */
3749f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (ppd->sdma_state.current_state !=
3750f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    qib_sdma_state_s20_idle)
3751f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				__qib_sdma_process_event(ppd,
3752f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					qib_sdma_event_e00_go_hw_down);
3753f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_unlock_irqrestore(&ppd->sdma_lock, flags);
3754f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
3755f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3756f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3757f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (symadj) {
3758f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ppd->cpspec->ibdeltainprog) {
3759f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->ibdeltainprog = 0;
3760f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->ibsymdelta += read_7220_creg32(ppd->dd,
3761f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				cr_ibsymbolerr) - ppd->cpspec->ibsymsnap;
3762f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->cpspec->iblnkerrdelta += read_7220_creg32(ppd->dd,
3763f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				cr_iblinkerrrecov) - ppd->cpspec->iblnkerrsnap;
3764f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
3765f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else if (!ibup && qib_compat_ddr_negotiate &&
3766f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		   !ppd->cpspec->ibdeltainprog &&
3767f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) {
3768f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibdeltainprog = 1;
3769f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->ibsymsnap = read_7220_creg32(ppd->dd,
3770f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell							  cr_ibsymbolerr);
3771f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->cpspec->iblnkerrsnap = read_7220_creg32(ppd->dd,
3772f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell						     cr_iblinkerrrecov);
3773f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3774f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3775f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!ret)
3776f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_setup_7220_setextled(ppd, ibup);
3777f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
3778f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3779f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3780f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3781f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Does read/modify/write to appropriate registers to
3782f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * set output and direction bits selected by mask.
3783f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * these are in their canonical postions (e.g. lsb of
3784f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * dir will end up in D48 of extctrl on existing chips).
3785f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * returns contents of GP Inputs.
3786f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3787f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int gpio_7220_mod(struct qib_devdata *dd, u32 out, u32 dir, u32 mask)
3788f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3789f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 read_val, new_out;
3790f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
3791f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3792f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (mask) {
3793f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* some bits being written, lock access to GPIO */
3794f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dir &= mask;
3795f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		out &= mask;
3796f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock_irqsave(&dd->cspec->gpio_lock, flags);
3797f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->extctrl &= ~((u64)mask << SYM_LSB(EXTCtrl, GPIOOe));
3798f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->extctrl |= ((u64) dir << SYM_LSB(EXTCtrl, GPIOOe));
3799f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		new_out = (dd->cspec->gpio_out & ~mask) | out;
3800f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3801f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_extctrl, dd->cspec->extctrl);
3802f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_gpio_out, new_out);
3803f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->gpio_out = new_out;
3804f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock_irqrestore(&dd->cspec->gpio_lock, flags);
3805f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3806f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
3807f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * It is unlikely that a read at this time would get valid
3808f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * data on a pin whose direction line was set in the same
3809f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * call to this function. We include the read here because
3810f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * that allows us to potentially combine a change on one pin with
3811f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * a read on another, and because the old code did something like
3812f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * this.
3813f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
3814f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	read_val = qib_read_kreg64(dd, kr_extstatus);
3815f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return SYM_FIELD(read_val, EXTStatus, GPIOIn);
3816f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3817f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3818f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3819f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Read fundamental info we need to use the chip.  These are
3820f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * the registers that describe chip capabilities, and are
3821f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * saved in shadow registers.
3822f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3823f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void get_7220_chip_params(struct qib_devdata *dd)
3824f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3825f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 val;
3826f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 piobufs;
3827f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int mtu;
3828f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3829f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->uregbase = qib_read_kreg32(dd, kr_userregbase);
3830f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3831f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->rcvtidcnt = qib_read_kreg32(dd, kr_rcvtidcnt);
3832f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->rcvtidbase = qib_read_kreg32(dd, kr_rcvtidbase);
3833f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->rcvegrbase = qib_read_kreg32(dd, kr_rcvegrbase);
3834f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->palign = qib_read_kreg32(dd, kr_palign);
3835f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->piobufbase = qib_read_kreg64(dd, kr_sendpiobufbase);
3836f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->pio2k_bufbase = dd->piobufbase & 0xffffffff;
3837f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3838f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	val = qib_read_kreg64(dd, kr_sendpiosize);
3839f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->piosize2k = val & ~0U;
3840f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->piosize4k = val >> 32;
3841f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3842f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	mtu = ib_mtu_enum_to_int(qib_ibmtu);
3843f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (mtu == -1)
3844f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		mtu = QIB_DEFAULT_MTU;
3845f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->pport->ibmtu = (u32)mtu;
3846f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3847f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	val = qib_read_kreg64(dd, kr_sendpiobufcnt);
3848f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->piobcnt2k = val & ~0U;
3849f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->piobcnt4k = val >> 32;
3850f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* these may be adjusted in init_chip_wc_pat() */
3851f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->pio2kbase = (u32 __iomem *)
3852f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		((char __iomem *) dd->kregbase + dd->pio2k_bufbase);
3853f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->piobcnt4k) {
3854f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->pio4kbase = (u32 __iomem *)
3855f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			((char __iomem *) dd->kregbase +
3856f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 (dd->piobufbase >> 32));
3857f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
3858f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * 4K buffers take 2 pages; we use roundup just to be
3859f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * paranoid; we calculate it once here, rather than on
3860f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * ever buf allocate
3861f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
3862f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->align4k = ALIGN(dd->piosize4k, dd->palign);
3863f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3864f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3865f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	piobufs = dd->piobcnt4k + dd->piobcnt2k;
3866f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3867f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->pioavregs = ALIGN(piobufs, sizeof(u64) * BITS_PER_BYTE / 2) /
3868f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		(sizeof(u64) * BITS_PER_BYTE / 2);
3869f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3870f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3871f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3872f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * The chip base addresses in cspec and cpspec have to be set
3873f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * after possible init_chip_wc_pat(), rather than in
3874f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_get_7220_chip_params(), so split out as separate function
3875f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3876f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void set_7220_baseaddrs(struct qib_devdata *dd)
3877f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3878f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 cregbase;
3879f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* init after possible re-map in init_chip_wc_pat() */
3880f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cregbase = qib_read_kreg32(dd, kr_counterregbase);
3881f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->cregbase = (u64 __iomem *)
3882f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		((char __iomem *) dd->kregbase + cregbase);
3883f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3884f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->egrtidbase = (u64 __iomem *)
3885f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		((char __iomem *) dd->kregbase + dd->rcvegrbase);
3886f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3887f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3888f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3889f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define SENDCTRL_SHADOWED (SYM_MASK(SendCtrl, SendIntBufAvail) |	\
3890f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			   SYM_MASK(SendCtrl, SPioEnable) |		\
3891f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			   SYM_MASK(SendCtrl, SSpecialTriggerEn) |	\
3892f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			   SYM_MASK(SendCtrl, SendBufAvailUpd) |	\
3893f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			   SYM_MASK(SendCtrl, AvailUpdThld) |		\
3894f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			   SYM_MASK(SendCtrl, SDmaEnable) |		\
3895f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			   SYM_MASK(SendCtrl, SDmaIntEnable) |		\
3896f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			   SYM_MASK(SendCtrl, SDmaHalt) |		\
3897f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			   SYM_MASK(SendCtrl, SDmaSingleDescriptor))
3898f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3899f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int sendctrl_hook(struct qib_devdata *dd,
3900f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 const struct diag_observer *op,
3901f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 u32 offs, u64 *data, u64 mask, int only_32)
3902f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3903f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
3904f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned idx = offs / sizeof(u64);
3905f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 local_data, all_bits;
3906f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3907f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (idx != kr_sendctrl) {
3908f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "SendCtrl Hook called with offs %X, %s-bit\n",
3909f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    offs, only_32 ? "32" : "64");
3910f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		return 0;
3911f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3912f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3913f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	all_bits = ~0ULL;
3914f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (only_32)
3915f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		all_bits >>= 32;
3916f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&dd->sendctrl_lock, flags);
3917f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if ((mask & all_bits) != all_bits) {
3918f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
3919f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * At least some mask bits are zero, so we need
3920f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * to read. The judgement call is whether from
3921f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * reg or shadow. First-cut: read reg, and complain
3922f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * if any bits which should be shadowed are different
3923f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * from their shadowed value.
3924f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
3925f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (only_32)
3926f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			local_data = (u64)qib_read_kreg32(dd, idx);
3927f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		else
3928f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			local_data = qib_read_kreg64(dd, idx);
3929f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "Sendctrl -> %X, Shad -> %X\n",
3930f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    (u32)local_data, (u32)dd->sendctrl);
3931f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if ((local_data & SENDCTRL_SHADOWED) !=
3932f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    (dd->sendctrl & SENDCTRL_SHADOWED))
3933f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_dev_err(dd, "Sendctrl read: %X shadow is %X\n",
3934f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				(u32)local_data, (u32) dd->sendctrl);
3935f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		*data = (local_data & ~mask) | (*data & mask);
3936f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3937f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (mask) {
3938f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
3939f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * At least some mask bits are one, so we need
3940f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * to write, but only shadow some bits.
3941f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
3942f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		u64 sval, tval; /* Shadowed, transient */
3943f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3944f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/*
3945f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * New shadow val is bits we don't want to touch,
3946f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 * ORed with bits we do, that are intended for shadow.
3947f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		 */
3948f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sval = (dd->sendctrl & ~mask);
3949f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sval |= *data & SENDCTRL_SHADOWED & mask;
3950f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->sendctrl = sval;
3951f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		tval = sval | (*data & ~SENDCTRL_SHADOWED & mask);
3952f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "Sendctrl <- %X, Shad <- %X\n",
3953f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    (u32)tval, (u32)sval);
3954f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_sendctrl, tval);
3955f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_scratch, 0Ull);
3956f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3957f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&dd->sendctrl_lock, flags);
3958f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3959f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return only_32 ? 4 : 8;
3960f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3961f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3962f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic const struct diag_observer sendctrl_observer = {
3963f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	sendctrl_hook, kr_sendctrl * sizeof(u64),
3964f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	kr_sendctrl * sizeof(u64)
3965f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell};
3966f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3967f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
3968f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * write the final few registers that depend on some of the
3969f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * init setup.  Done late in init, just before bringing up
3970f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * the serdes.
3971f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
3972f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_late_7220_initreg(struct qib_devdata *dd)
3973f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3974f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int ret = 0;
3975f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 val;
3976f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3977f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_rcvhdrentsize, dd->rcvhdrentsize);
3978f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_rcvhdrsize, dd->rcvhdrsize);
3979f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_rcvhdrcnt, dd->rcvhdrcnt);
3980f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_sendpioavailaddr, dd->pioavailregs_phys);
3981f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	val = qib_read_kreg64(dd, kr_sendpioavailaddr);
3982f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (val != dd->pioavailregs_phys) {
3983f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "Catastrophic software error, "
3984f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    "SendPIOAvailAddr written as %lx, "
3985f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    "read back as %llx\n",
3986f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    (unsigned long) dd->pioavailregs_phys,
3987f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    (unsigned long long) val);
3988f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = -EINVAL;
3989f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
3990f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_register_observer(dd, &sendctrl_observer);
3991f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
3992f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
3993f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
3994f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_init_7220_variables(struct qib_devdata *dd)
3995f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
3996f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_chippport_specific *cpspec;
3997f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_pportdata *ppd;
3998f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int ret = 0;
3999f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 sbufs, updthresh;
4000f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4001f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cpspec = (struct qib_chippport_specific *)(dd + 1);
4002f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd = &cpspec->pportdata;
4003f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->pport = ppd;
4004f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->num_pports = 1;
4005f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4006f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec = (struct qib_chip_specific *)(cpspec + dd->num_pports);
4007f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->cpspec = cpspec;
4008f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4009f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_init(&dd->cspec->sdepb_lock);
4010f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_init(&dd->cspec->rcvmod_lock);
4011f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_init(&dd->cspec->gpio_lock);
4012f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4013f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* we haven't yet set QIB_PRESENT, so use read directly */
4014f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->revision = readq(&dd->kregbase[kr_revision]);
4015f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4016f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if ((dd->revision & 0xffffffffU) == 0xffffffffU) {
4017f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "Revision register read failure, "
4018f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    "giving up initialization\n");
4019f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = -ENODEV;
4020f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
4021f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
4022f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->flags |= QIB_PRESENT;  /* now register routines work */
4023f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4024f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->majrev = (u8) SYM_FIELD(dd->revision, Revision_R,
4025f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				    ChipRevMajor);
4026f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->minrev = (u8) SYM_FIELD(dd->revision, Revision_R,
4027f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				    ChipRevMinor);
4028f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4029f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	get_7220_chip_params(dd);
4030f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_7220_boardname(dd);
4031f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4032f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
4033f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * GPIO bits for TWSI data and clock,
4034f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * used for serial EEPROM.
4035f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
4036f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->gpio_sda_num = _QIB_GPIO_SDA_NUM;
4037f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->gpio_scl_num = _QIB_GPIO_SCL_NUM;
4038f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->twsi_eeprom_dev = QIB_TWSI_EEPROM_DEV;
4039f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4040f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->flags |= QIB_HAS_INTX | QIB_HAS_LINK_LATENCY |
4041f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QIB_NODMA_RTAIL | QIB_HAS_THRESH_UPDATE;
4042f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->flags |= qib_special_trigger ?
4043f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		QIB_USE_SPCL_TRIG : QIB_HAS_SEND_DMA;
4044f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4045f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
4046f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
4047f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * 2 is Some Misc, 3 is reserved for future.
4048f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
4049f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->eep_st_masks[0].hwerrs_to_log = HWE_MASK(TXEMemParityErr);
4050f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4051f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->eep_st_masks[1].hwerrs_to_log = HWE_MASK(RXEMemParityErr);
4052f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4053f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->eep_st_masks[2].errs_to_log = ERR_MASK(ResetNegated);
4054f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4055f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	init_waitqueue_head(&cpspec->autoneg_wait);
4056f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	INIT_DELAYED_WORK(&cpspec->autoneg_work, autoneg_7220_work);
4057f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4058f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_init_pportdata(ppd, dd, 0, 1);
4059f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
4060f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->link_speed_supported = QIB_IB_SDR | QIB_IB_DDR;
4061f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4062f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->link_width_enabled = ppd->link_width_supported;
4063f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->link_speed_enabled = ppd->link_speed_supported;
4064f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
4065f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Set the initial values to reasonable default, will be set
4066f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * for real when link is up.
4067f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
4068f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->link_width_active = IB_WIDTH_4X;
4069f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->link_speed_active = QIB_IB_SDR;
4070f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->delay_mult = rate_to_delay[0][1];
4071f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->vls_supported = IB_VL_VL0;
4072f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->vls_operational = ppd->vls_supported;
4073f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4074f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!qib_mini_init)
4075f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_rcvbthqp, QIB_KD_QP);
4076f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4077f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	init_timer(&ppd->cpspec->chase_timer);
4078f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->cpspec->chase_timer.function = reenable_7220_chase;
4079f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->cpspec->chase_timer.data = (unsigned long)ppd;
4080f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4081f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_num_cfg_vls = 1; /* if any 7220's, only one VL */
4082f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4083f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->rcvhdrentsize = QIB_RCVHDR_ENTSIZE;
4084f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->rcvhdrsize = QIB_DFLT_RCVHDRSIZE;
4085f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->rhf_offset =
4086f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->rcvhdrentsize - sizeof(u64) / sizeof(u32);
4087f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4088f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* we always allocate at least 2048 bytes for eager buffers */
4089f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = ib_mtu_enum_to_int(qib_ibmtu);
4090f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
40919e1c0e43257b6df1ef012dd37c3f0f93b1ee47afMike Marciniszyn	BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
40929e1c0e43257b6df1ef012dd37c3f0f93b1ee47afMike Marciniszyn	dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
4093f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4094f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_7220_tidtemplate(dd);
4095f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4096f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
4097f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * We can request a receive interrupt for 1 or
4098f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * more packets from current offset.  For now, we set this
4099f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * up for a single packet.
4100f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
4101f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->rhdrhead_intr_off = 1ULL << 32;
4102f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4103f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* setup the stats timer; the add_timer is done at end of init */
4104f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	init_timer(&dd->stats_timer);
4105f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->stats_timer.function = qib_get_7220_faststats;
4106f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->stats_timer.data = (unsigned long) dd;
4107f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->stats_timer.expires = jiffies + ACTIVITY_TIMER * HZ;
4108f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4109f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
4110f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Control[4] has been added to change the arbitration within
4111f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * the SDMA engine between favoring data fetches over descriptor
4112f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * fetches.  qib_sdma_fetch_arb==0 gives data fetches priority.
4113f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
4114f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qib_sdma_fetch_arb)
4115f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->control |= 1 << 4;
4116f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4117f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->ureg_align = 0x10000;  /* 64KB alignment */
4118f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4119f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->piosize2kmax_dwords = (dd->piosize2k >> 2)-1;
4120f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_7220_config_ctxts(dd);
4121f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_set_ctxtcnt(dd);  /* needed for PAT setup */
4122f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4123f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qib_wc_pat) {
4124f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = init_chip_wc_pat(dd, 0);
4125f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ret)
4126f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto bail;
4127f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
4128f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	set_7220_baseaddrs(dd); /* set chip access pointers now */
4129f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4130f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = 0;
4131f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qib_mini_init)
4132f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
4133f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4134f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = qib_create_ctxts(dd);
4135f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	init_7220_cntrnames(dd);
4136f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4137f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* use all of 4KB buffers for the kernel SDMA, zero if !SDMA.
4138f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * reserve the update threshold amount for other kernel use, such
4139f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * as sending SMI, MAD, and ACKs, or 3, whichever is greater,
4140f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * unless we aren't enabling SDMA, in which case we want to use
4141f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * all the 4k bufs for the kernel.
4142f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * if this was less than the update threshold, we could wait
4143f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * a long time for an update.  Coded this way because we
4144f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * sometimes change the update threshold for various reasons,
4145f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * and we want this to remain robust.
4146f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
4147f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	updthresh = 8U; /* update threshold */
4148f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (dd->flags & QIB_HAS_SEND_DMA) {
4149f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->sdmabufcnt =  dd->piobcnt4k;
4150f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sbufs = updthresh > 3 ? updthresh : 3;
4151f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else {
4152f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->sdmabufcnt = 0;
4153f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sbufs = dd->piobcnt4k;
4154f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
4155f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4156f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->lastbuf_for_pio = dd->piobcnt2k + dd->piobcnt4k -
4157f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		dd->cspec->sdmabufcnt;
4158f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->lastctxt_piobuf = dd->cspec->lastbuf_for_pio - sbufs;
4159f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->lastbuf_for_pio--; /* range is <= , not < */
4160f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->pbufsctxt = dd->lastctxt_piobuf /
4161f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		(dd->cfgctxts - dd->first_user_ctxt);
4162f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4163f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
4164f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * if we are at 16 user contexts, we will have one 7 sbufs
4165f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * per context, so drop the update threshold to match.  We
4166f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * want to update before we actually run out, at low pbufs/ctxt
4167f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * so give ourselves some margin
4168f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
4169f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if ((dd->pbufsctxt - 2) < updthresh)
4170f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		updthresh = dd->pbufsctxt - 2;
4171f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4172f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->updthresh_dflt = updthresh;
4173f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->updthresh = updthresh;
4174f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4175f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* before full enable, no interrupts, no locking needed */
4176f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->sendctrl |= (updthresh & SYM_RMASK(SendCtrl, AvailUpdThld))
4177f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			     << SYM_LSB(SendCtrl, AvailUpdThld);
4178f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4179f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->psxmitwait_supported = 1;
4180f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->psxmitwait_check_rate = QIB_7220_PSXMITWAIT_CHECK_RATE;
4181f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail:
4182f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
4183f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4184f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4185f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u32 __iomem *qib_7220_getsendbuf(struct qib_pportdata *ppd, u64 pbc,
4186f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					u32 *pbufnum)
4187f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4188f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 first, last, plen = pbc & QIB_PBC_LENGTH_MASK;
4189f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
4190f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 __iomem *buf;
4191f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4192f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (((pbc >> 32) & PBC_7220_VL15_SEND_CTRL) &&
4193f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		!(ppd->lflags & (QIBL_IB_AUTONEG_INPROG | QIBL_LINKACTIVE)))
4194f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		buf = get_7220_link_buf(ppd, pbufnum);
4195f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	else {
4196f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if ((plen + 1) > dd->piosize2kmax_dwords)
4197f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			first = dd->piobcnt2k;
4198f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		else
4199f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			first = 0;
4200f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* try 4k if all 2k busy, so same last for both sizes */
4201f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		last = dd->cspec->lastbuf_for_pio;
4202f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		buf = qib_getsendbuf_range(dd, pbufnum, first, last);
4203f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
4204f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return buf;
4205f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4206f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4207f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* these 2 "counters" are really control registers, and are always RW */
4208f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_set_cntr_7220_sample(struct qib_pportdata *ppd, u32 intv,
4209f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				     u32 start)
4210f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4211f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	write_7220_creg(ppd->dd, cr_psinterval, intv);
4212f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	write_7220_creg(ppd->dd, cr_psstart, start);
4213f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4214f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4215f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
4216f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * NOTE: no real attempt is made to generalize the SDMA stuff.
4217f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * At some point "soon" we will have a new more generalized
4218f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * set of sdma interface, and then we'll clean this up.
4219f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
4220f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4221f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* Must be called with sdma_lock held, or before init finished */
4222f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_sdma_update_7220_tail(struct qib_pportdata *ppd, u16 tail)
4223f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4224f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* Commit writes to memory and advance the tail on the chip */
4225f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	wmb();
4226f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->sdma_descq_tail = tail;
4227f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(ppd->dd, kr_senddmatail, tail);
4228f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4229f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4230f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_sdma_set_7220_desc_cnt(struct qib_pportdata *ppd, unsigned cnt)
4231f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4232f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4233f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4234f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic struct sdma_set_state_action sdma_7220_action_table[] = {
4235f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[qib_sdma_state_s00_hw_down] = {
4236f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_enable = 0,
4237f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_intenable = 0,
4238f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_halt = 0,
4239f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.go_s99_running_tofalse = 1,
4240f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	},
4241f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[qib_sdma_state_s10_hw_start_up_wait] = {
4242f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_enable = 1,
4243f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_intenable = 1,
4244f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_halt = 1,
4245f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	},
4246f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[qib_sdma_state_s20_idle] = {
4247f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_enable = 1,
4248f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_intenable = 1,
4249f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_halt = 1,
4250f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	},
4251f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[qib_sdma_state_s30_sw_clean_up_wait] = {
4252f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_enable = 0,
4253f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_intenable = 1,
4254f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_halt = 0,
4255f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	},
4256f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[qib_sdma_state_s40_hw_clean_up_wait] = {
4257f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_enable = 1,
4258f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_intenable = 1,
4259f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_halt = 1,
4260f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	},
4261f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[qib_sdma_state_s50_hw_halt_wait] = {
4262f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_enable = 1,
4263f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_intenable = 1,
4264f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_halt = 1,
4265f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	},
4266f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	[qib_sdma_state_s99_running] = {
4267f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_enable = 1,
4268f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_intenable = 1,
4269f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.op_halt = 0,
4270f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		.go_s99_running_totrue = 1,
4271f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	},
4272f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell};
4273f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4274f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_sdma_init_early(struct qib_pportdata *ppd)
4275f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4276f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->sdma_state.set_state_action = sdma_7220_action_table;
4277f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4278f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4279f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int init_sdma_7220_regs(struct qib_pportdata *ppd)
4280f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4281f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
4282f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned i, n;
4283f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 senddmabufmask[3] = { 0 };
4284f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4285f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* Set SendDmaBase */
4286f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_senddmabase, ppd->sdma_descq_phys);
4287f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_sdma_7220_setlengen(ppd);
4288f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_sdma_update_7220_tail(ppd, 0); /* Set SendDmaTail */
4289f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* Set SendDmaHeadAddr */
4290f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_senddmaheadaddr, ppd->sdma_head_phys);
4291f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4292f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
4293f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Reserve all the former "kernel" piobufs, using high number range
4294f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * so we get as many 4K buffers as possible
4295f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
4296f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	n = dd->piobcnt2k + dd->piobcnt4k;
4297f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	i = n - dd->cspec->sdmabufcnt;
4298f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4299f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (; i < n; ++i) {
4300f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		unsigned word = i / 64;
4301f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		unsigned bit = i & 63;
4302f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4303f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		BUG_ON(word >= 3);
4304f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		senddmabufmask[word] |= 1ULL << bit;
4305f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
4306f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_senddmabufmask0, senddmabufmask[0]);
4307f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_senddmabufmask1, senddmabufmask[1]);
4308f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_senddmabufmask2, senddmabufmask[2]);
4309f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4310f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->sdma_state.first_sendbuf = i;
4311f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->sdma_state.last_sendbuf = n;
4312f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4313f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return 0;
4314f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4315f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4316f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* sdma_lock must be held */
4317f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u16 qib_sdma_7220_gethead(struct qib_pportdata *ppd)
4318f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4319f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
4320f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int sane;
4321f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int use_dmahead;
4322f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u16 swhead;
4323f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u16 swtail;
4324f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u16 cnt;
4325f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u16 hwhead;
4326f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4327f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	use_dmahead = __qib_sdma_running(ppd) &&
4328f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		(dd->flags & QIB_HAS_SDMA_TIMEOUT);
4329f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellretry:
4330f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	hwhead = use_dmahead ?
4331f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		(u16)le64_to_cpu(*ppd->sdma_head_dma) :
4332f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		(u16)qib_read_kreg32(dd, kr_senddmahead);
4333f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4334f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	swhead = ppd->sdma_descq_head;
4335f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	swtail = ppd->sdma_descq_tail;
4336f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	cnt = ppd->sdma_descq_cnt;
4337f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4338f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (swhead < swtail) {
4339f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* not wrapped */
4340f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sane = (hwhead >= swhead) & (hwhead <= swtail);
4341f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else if (swhead > swtail) {
4342f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* wrapped around */
4343f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sane = ((hwhead >= swhead) && (hwhead < cnt)) ||
4344f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			(hwhead <= swtail);
4345f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else {
4346f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* empty */
4347f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sane = (hwhead == swhead);
4348f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
4349f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4350f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (unlikely(!sane)) {
4351f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (use_dmahead) {
4352f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/* try one more time, directly from the register */
4353f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			use_dmahead = 0;
4354f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto retry;
4355f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
4356f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* assume no progress */
4357f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		hwhead = swhead;
4358f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
4359f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4360f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return hwhead;
4361f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4362f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4363f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_sdma_7220_busy(struct qib_pportdata *ppd)
4364f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4365f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u64 hwstatus = qib_read_kreg64(ppd->dd, kr_senddmastatus);
4366f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4367f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return (hwstatus & SYM_MASK(SendDmaStatus, ScoreBoardDrainInProg)) ||
4368f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	       (hwstatus & SYM_MASK(SendDmaStatus, AbortInProg)) ||
4369f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	       (hwstatus & SYM_MASK(SendDmaStatus, InternalSDmaEnable)) ||
4370f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	       !(hwstatus & SYM_MASK(SendDmaStatus, ScbEmpty));
4371f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4372f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4373f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
4374f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Compute the amount of delay before sending the next packet if the
4375f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * port's send rate differs from the static rate set for the QP.
4376f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Since the delay affects this packet but the amount of the delay is
4377f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * based on the length of the previous packet, use the last delay computed
4378f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * and save the delay count for this packet to be used next time
4379f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * we get here.
4380f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
4381f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic u32 qib_7220_setpbc_control(struct qib_pportdata *ppd, u32 plen,
4382f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				   u8 srate, u8 vl)
4383f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4384f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u8 snd_mult = ppd->delay_mult;
4385f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u8 rcv_mult = ib_rate_to_delay[srate];
4386f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 ret = ppd->cpspec->last_delay_mult;
4387f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4388f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->cpspec->last_delay_mult = (rcv_mult > snd_mult) ?
4389f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		(plen * (rcv_mult - snd_mult) + 1) >> 1 : 0;
4390f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4391f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* Indicate VL15, if necessary */
4392f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (vl == 15)
4393f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret |= PBC_7220_VL15_SEND_CTRL;
4394f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
4395f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4396f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4397f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_initvl15_bufs(struct qib_devdata *dd)
4398f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4399f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4400f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4401f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_init_ctxt(struct qib_ctxtdata *rcd)
4402f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4403f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!rcd->ctxt) {
4404f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		rcd->rcvegrcnt = IBA7220_KRCVEGRCNT;
4405f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		rcd->rcvegr_tid_base = 0;
4406f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else {
4407f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		rcd->rcvegrcnt = rcd->dd->cspec->rcvegrcnt;
4408f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		rcd->rcvegr_tid_base = IBA7220_KRCVEGRCNT +
4409f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			(rcd->ctxt - 1) * rcd->rcvegrcnt;
4410f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
4411f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4412f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4413f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_7220_txchk_change(struct qib_devdata *dd, u32 start,
4414f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				  u32 len, u32 which, struct qib_ctxtdata *rcd)
4415f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4416f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int i;
4417f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
4418f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4419f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	switch (which) {
4420f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case TXCHK_CHG_TYPE_KERN:
4421f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* see if we need to raise avail update threshold */
4422f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock_irqsave(&dd->uctxt_lock, flags);
4423f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		for (i = dd->first_user_ctxt;
4424f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		     dd->cspec->updthresh != dd->cspec->updthresh_dflt
4425f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		     && i < dd->cfgctxts; i++)
4426f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (dd->rcd[i] && dd->rcd[i]->subctxt_cnt &&
4427f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			   ((dd->rcd[i]->piocnt / dd->rcd[i]->subctxt_cnt) - 1)
4428f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			   < dd->cspec->updthresh_dflt)
4429f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				break;
4430f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock_irqrestore(&dd->uctxt_lock, flags);
4431f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (i == dd->cfgctxts) {
4432f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_lock_irqsave(&dd->sendctrl_lock, flags);
4433f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->cspec->updthresh = dd->cspec->updthresh_dflt;
4434f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->sendctrl &= ~SYM_MASK(SendCtrl, AvailUpdThld);
4435f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->sendctrl |= (dd->cspec->updthresh &
4436f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					 SYM_RMASK(SendCtrl, AvailUpdThld)) <<
4437f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					   SYM_LSB(SendCtrl, AvailUpdThld);
4438f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_unlock_irqrestore(&dd->sendctrl_lock, flags);
4439f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			sendctrl_7220_mod(dd->pport, QIB_SENDCTRL_AVAIL_BLIP);
4440f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
4441f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
4442f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case TXCHK_CHG_TYPE_USER:
4443f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock_irqsave(&dd->sendctrl_lock, flags);
4444f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (rcd && rcd->subctxt_cnt && ((rcd->piocnt
4445f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/ rcd->subctxt_cnt) - 1) < dd->cspec->updthresh) {
4446f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->cspec->updthresh = (rcd->piocnt /
4447f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell						rcd->subctxt_cnt) - 1;
4448f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->sendctrl &= ~SYM_MASK(SendCtrl, AvailUpdThld);
4449f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->sendctrl |= (dd->cspec->updthresh &
4450f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					SYM_RMASK(SendCtrl, AvailUpdThld))
4451f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					<< SYM_LSB(SendCtrl, AvailUpdThld);
4452f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_unlock_irqrestore(&dd->sendctrl_lock, flags);
4453f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			sendctrl_7220_mod(dd->pport, QIB_SENDCTRL_AVAIL_BLIP);
4454f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else
4455f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_unlock_irqrestore(&dd->sendctrl_lock, flags);
4456f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
4457f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
4458f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4459f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4460f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void writescratch(struct qib_devdata *dd, u32 val)
4461f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4462f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_scratch, val);
4463f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4464f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4465f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#define VALID_TS_RD_REG_MASK 0xBF
4466f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
4467f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_7220_tempsense_read - read register of temp sensor via TWSI
4468f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dd: the qlogic_ib device
4469f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @regnum: register to read from
4470f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
4471f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * returns reg contents (0..255) or < 0 for error
4472f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
4473f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_7220_tempsense_rd(struct qib_devdata *dd, int regnum)
4474f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4475f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int ret;
4476f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u8 rdata;
4477f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4478f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (regnum > 7) {
4479f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = -EINVAL;
4480f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
4481f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
4482f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4483f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* return a bogus value for (the one) register we do not have */
4484f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!((1 << regnum) & VALID_TS_RD_REG_MASK)) {
4485f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = 0;
4486f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
4487f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
4488f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4489f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = mutex_lock_interruptible(&dd->eep_lock);
4490f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ret)
4491f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
4492f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4493f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = qib_twsi_blk_rd(dd, QIB_TWSI_TEMP_DEV, regnum, &rdata, 1);
4494f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (!ret)
4495f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ret = rdata;
4496f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4497f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	mutex_unlock(&dd->eep_lock);
4498f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4499f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
4500f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * There are three possibilities here:
4501f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * ret is actual value (0..255)
4502f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * ret is -ENXIO or -EINVAL from twsi code or this file
4503f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * ret is -EINTR from mutex_lock_interruptible.
4504f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
4505f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail:
4506f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return ret;
4507f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4508f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4509f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/* Dummy function, as 7220 boards never disable EEPROM Write */
4510f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic int qib_7220_eeprom_wen(struct qib_devdata *dd, int wen)
4511f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4512f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return 1;
4513f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4514f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4515f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
4516f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_init_iba7220_funcs - set up the chip-specific function pointers
4517f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @dev: the pci_dev for qlogic_ib device
4518f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @ent: pci_device_id struct for this dev
4519f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
4520f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This is global, and is called directly at init to set up the
4521f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * chip-specific function pointers for later use.
4522f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
4523f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstruct qib_devdata *qib_init_iba7220_funcs(struct pci_dev *pdev,
4524f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					   const struct pci_device_id *ent)
4525f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
4526f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd;
4527f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int ret;
4528f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 boardid, minwidth;
4529f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4530f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd = qib_alloc_devdata(pdev, sizeof(struct qib_chip_specific) +
4531f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		sizeof(struct qib_chippport_specific));
4532f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (IS_ERR(dd))
4533f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
4534f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4535f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_bringup_serdes    = qib_7220_bringup_serdes;
4536f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_cleanup           = qib_setup_7220_cleanup;
4537f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_clear_tids        = qib_7220_clear_tids;
4538f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_free_irq          = qib_7220_free_irq;
4539f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_get_base_info     = qib_7220_get_base_info;
4540f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_get_msgheader     = qib_7220_get_msgheader;
4541f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_getsendbuf        = qib_7220_getsendbuf;
4542f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_gpio_mod          = gpio_7220_mod;
4543f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_eeprom_wen        = qib_7220_eeprom_wen;
4544f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_hdrqempty         = qib_7220_hdrqempty;
4545f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_ib_updown         = qib_7220_ib_updown;
4546f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_init_ctxt         = qib_7220_init_ctxt;
4547f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_initvl15_bufs     = qib_7220_initvl15_bufs;
4548f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_intr_fallback     = qib_7220_intr_fallback;
4549f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_late_initreg      = qib_late_7220_initreg;
4550f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_setpbc_control    = qib_7220_setpbc_control;
4551f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_portcntr          = qib_portcntr_7220;
4552f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_put_tid           = qib_7220_put_tid;
4553f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_quiet_serdes      = qib_7220_quiet_serdes;
4554f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_rcvctrl           = rcvctrl_7220_mod;
4555f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_read_cntrs        = qib_read_7220cntrs;
4556f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_read_portcntrs    = qib_read_7220portcntrs;
4557f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_reset             = qib_setup_7220_reset;
4558f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_init_sdma_regs    = init_sdma_7220_regs;
4559f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_sdma_busy         = qib_sdma_7220_busy;
4560f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_sdma_gethead      = qib_sdma_7220_gethead;
4561f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_sdma_sendctrl     = qib_7220_sdma_sendctrl;
4562f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_sdma_set_desc_cnt = qib_sdma_set_7220_desc_cnt;
4563f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_sdma_update_tail  = qib_sdma_update_7220_tail;
4564f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_sdma_hw_clean_up  = qib_7220_sdma_hw_clean_up;
4565f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_sdma_hw_start_up  = qib_7220_sdma_hw_start_up;
4566f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_sdma_init_early   = qib_7220_sdma_init_early;
4567f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_sendctrl          = sendctrl_7220_mod;
4568f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_set_armlaunch     = qib_set_7220_armlaunch;
4569f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_set_cntr_sample   = qib_set_cntr_7220_sample;
4570f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_iblink_state      = qib_7220_iblink_state;
4571f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_ibphys_portstate  = qib_7220_phys_portstate;
4572f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_get_ib_cfg        = qib_7220_get_ib_cfg;
4573f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_set_ib_cfg        = qib_7220_set_ib_cfg;
4574f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_set_ib_loopback   = qib_7220_set_loopback;
4575f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_set_intr_state    = qib_7220_set_intr_state;
4576f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_setextled         = qib_setup_7220_setextled;
4577f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_txchk_change      = qib_7220_txchk_change;
4578f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_update_usrhead    = qib_update_7220_usrhead;
4579f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_wantpiobuf_intr   = qib_wantpiobuf_7220_intr;
4580f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_xgxs_reset        = qib_7220_xgxs_reset;
4581f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_writescratch      = writescratch;
4582f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->f_tempsense_rd	= qib_7220_tempsense_rd;
4583f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
4584f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Do remaining pcie setup and save pcie values in dd.
4585f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * Any error printing is already done by the init code.
4586f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * On return, we have the chip mapped, but chip registers
4587f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * are not set up until start of qib_init_7220_variables.
4588f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
4589f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = qib_pcie_ddinit(dd, pdev, ent);
4590f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ret < 0)
4591f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail_free;
4592f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4593f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* initialize chip-specific variables */
4594f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ret = qib_init_7220_variables(dd);
4595f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ret)
4596f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail_cleanup;
4597f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4598f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qib_mini_init)
4599f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		goto bail;
4600f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4601f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	boardid = SYM_FIELD(dd->revision, Revision,
4602f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    BoardID);
4603f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	switch (boardid) {
4604f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case 0:
4605f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case 2:
4606f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case 10:
4607f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	case 12:
4608f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		minwidth = 16; /* x16 capable boards */
4609f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
4610f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	default:
4611f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		minwidth = 8; /* x8 capable boards */
4612f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		break;
4613f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
4614f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qib_pcie_params(dd, minwidth, NULL, NULL))
4615f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_dev_err(dd, "Failed to setup PCIe or interrupts; "
4616f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			    "continuing anyway\n");
4617f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4618f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* save IRQ for possible later use */
4619f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd->cspec->irq = pdev->irq;
4620f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4621f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (qib_read_kreg64(dd, kr_hwerrstatus) &
4622f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	    QLOGIC_IB_HWE_SERDESPLLFAILED)
4623f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_write_kreg(dd, kr_hwerrclear,
4624f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			       QLOGIC_IB_HWE_SERDESPLLFAILED);
4625f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4626f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* setup interrupt handler (interrupt type handled above) */
4627f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_setup_7220_interrupt(dd);
4628f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_7220_init_hwerrors(dd);
4629f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4630f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* clear diagctrl register, in case diags were running and crashed */
4631f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_write_kreg(dd, kr_hwdiagctrl, 0);
4632f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4633f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	goto bail;
4634f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
4635f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail_cleanup:
4636f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_pcie_ddcleanup(dd);
4637f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail_free:
4638f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	qib_free_devdata(dd);
4639f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	dd = ERR_PTR(ret);
4640f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellbail:
4641f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return dd;
4642f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
4643