18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (c) 2013 Intel Corporation. All rights reserved.
38c2ecf20Sopenharmony_ci * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved.
48c2ecf20Sopenharmony_ci * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two
78c2ecf20Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
88c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
98c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the
108c2ecf20Sopenharmony_ci * OpenIB.org BSD license below:
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci *     Redistribution and use in source and binary forms, with or
138c2ecf20Sopenharmony_ci *     without modification, are permitted provided that the following
148c2ecf20Sopenharmony_ci *     conditions are met:
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci *      - Redistributions of source code must retain the above
178c2ecf20Sopenharmony_ci *        copyright notice, this list of conditions and the following
188c2ecf20Sopenharmony_ci *        disclaimer.
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci *      - Redistributions in binary form must reproduce the above
218c2ecf20Sopenharmony_ci *        copyright notice, this list of conditions and the following
228c2ecf20Sopenharmony_ci *        disclaimer in the documentation and/or other materials
238c2ecf20Sopenharmony_ci *        provided with the distribution.
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
268c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
278c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
288c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
298c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
308c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
318c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
328c2ecf20Sopenharmony_ci * SOFTWARE.
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
368c2ecf20Sopenharmony_ci#include <linux/pci.h>
378c2ecf20Sopenharmony_ci#include <linux/io.h>
388c2ecf20Sopenharmony_ci#include <linux/delay.h>
398c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
408c2ecf20Sopenharmony_ci#include <linux/vmalloc.h>
418c2ecf20Sopenharmony_ci#include <linux/module.h>
428c2ecf20Sopenharmony_ci#include <linux/prefetch.h>
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#include "qib.h"
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/*
478c2ecf20Sopenharmony_ci * The size has to be longer than this string, so we can append
488c2ecf20Sopenharmony_ci * board/chip information to it in the init code.
498c2ecf20Sopenharmony_ci */
508c2ecf20Sopenharmony_ciconst char ib_qib_version[] = QIB_DRIVER_VERSION "\n";
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ciDEFINE_MUTEX(qib_mutex);	/* general driver use */
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ciunsigned qib_ibmtu;
558c2ecf20Sopenharmony_cimodule_param_named(ibmtu, qib_ibmtu, uint, S_IRUGO);
568c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ibmtu, "Set max IB MTU (0=2KB, 1=256, 2=512, ... 5=4096");
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ciunsigned qib_compat_ddr_negotiate = 1;
598c2ecf20Sopenharmony_cimodule_param_named(compat_ddr_negotiate, qib_compat_ddr_negotiate, uint,
608c2ecf20Sopenharmony_ci		   S_IWUSR | S_IRUGO);
618c2ecf20Sopenharmony_ciMODULE_PARM_DESC(compat_ddr_negotiate,
628c2ecf20Sopenharmony_ci		 "Attempt pre-IBTA 1.2 DDR speed negotiation");
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
658c2ecf20Sopenharmony_ciMODULE_AUTHOR("Intel <ibsupport@intel.com>");
668c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Intel IB driver");
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci/*
698c2ecf20Sopenharmony_ci * QIB_PIO_MAXIBHDR is the max IB header size allowed for in our
708c2ecf20Sopenharmony_ci * PIO send buffers.  This is well beyond anything currently
718c2ecf20Sopenharmony_ci * defined in the InfiniBand spec.
728c2ecf20Sopenharmony_ci */
738c2ecf20Sopenharmony_ci#define QIB_PIO_MAXIBHDR 128
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci/*
768c2ecf20Sopenharmony_ci * QIB_MAX_PKT_RCV is the max # if packets processed per receive interrupt.
778c2ecf20Sopenharmony_ci */
788c2ecf20Sopenharmony_ci#define QIB_MAX_PKT_RECV 64
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistruct qlogic_ib_stats qib_stats;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistruct pci_dev *qib_get_pci_dev(struct rvt_dev_info *rdi)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	struct qib_ibdev *ibdev = container_of(rdi, struct qib_ibdev, rdi);
858c2ecf20Sopenharmony_ci	struct qib_devdata *dd = container_of(ibdev,
868c2ecf20Sopenharmony_ci					      struct qib_devdata, verbs_dev);
878c2ecf20Sopenharmony_ci	return dd->pcidev;
888c2ecf20Sopenharmony_ci}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci/*
918c2ecf20Sopenharmony_ci * Return count of units with at least one port ACTIVE.
928c2ecf20Sopenharmony_ci */
938c2ecf20Sopenharmony_ciint qib_count_active_units(void)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	struct qib_devdata *dd;
968c2ecf20Sopenharmony_ci	struct qib_pportdata *ppd;
978c2ecf20Sopenharmony_ci	unsigned long index, flags;
988c2ecf20Sopenharmony_ci	int pidx, nunits_active = 0;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	xa_lock_irqsave(&qib_dev_table, flags);
1018c2ecf20Sopenharmony_ci	xa_for_each(&qib_dev_table, index, dd) {
1028c2ecf20Sopenharmony_ci		if (!(dd->flags & QIB_PRESENT) || !dd->kregbase)
1038c2ecf20Sopenharmony_ci			continue;
1048c2ecf20Sopenharmony_ci		for (pidx = 0; pidx < dd->num_pports; ++pidx) {
1058c2ecf20Sopenharmony_ci			ppd = dd->pport + pidx;
1068c2ecf20Sopenharmony_ci			if (ppd->lid && (ppd->lflags & (QIBL_LINKINIT |
1078c2ecf20Sopenharmony_ci					 QIBL_LINKARMED | QIBL_LINKACTIVE))) {
1088c2ecf20Sopenharmony_ci				nunits_active++;
1098c2ecf20Sopenharmony_ci				break;
1108c2ecf20Sopenharmony_ci			}
1118c2ecf20Sopenharmony_ci		}
1128c2ecf20Sopenharmony_ci	}
1138c2ecf20Sopenharmony_ci	xa_unlock_irqrestore(&qib_dev_table, flags);
1148c2ecf20Sopenharmony_ci	return nunits_active;
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci/*
1188c2ecf20Sopenharmony_ci * Return count of all units, optionally return in arguments
1198c2ecf20Sopenharmony_ci * the number of usable (present) units, and the number of
1208c2ecf20Sopenharmony_ci * ports that are up.
1218c2ecf20Sopenharmony_ci */
1228c2ecf20Sopenharmony_ciint qib_count_units(int *npresentp, int *nupp)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	int nunits = 0, npresent = 0, nup = 0;
1258c2ecf20Sopenharmony_ci	struct qib_devdata *dd;
1268c2ecf20Sopenharmony_ci	unsigned long index, flags;
1278c2ecf20Sopenharmony_ci	int pidx;
1288c2ecf20Sopenharmony_ci	struct qib_pportdata *ppd;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	xa_lock_irqsave(&qib_dev_table, flags);
1318c2ecf20Sopenharmony_ci	xa_for_each(&qib_dev_table, index, dd) {
1328c2ecf20Sopenharmony_ci		nunits++;
1338c2ecf20Sopenharmony_ci		if ((dd->flags & QIB_PRESENT) && dd->kregbase)
1348c2ecf20Sopenharmony_ci			npresent++;
1358c2ecf20Sopenharmony_ci		for (pidx = 0; pidx < dd->num_pports; ++pidx) {
1368c2ecf20Sopenharmony_ci			ppd = dd->pport + pidx;
1378c2ecf20Sopenharmony_ci			if (ppd->lid && (ppd->lflags & (QIBL_LINKINIT |
1388c2ecf20Sopenharmony_ci					 QIBL_LINKARMED | QIBL_LINKACTIVE)))
1398c2ecf20Sopenharmony_ci				nup++;
1408c2ecf20Sopenharmony_ci		}
1418c2ecf20Sopenharmony_ci	}
1428c2ecf20Sopenharmony_ci	xa_unlock_irqrestore(&qib_dev_table, flags);
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	if (npresentp)
1458c2ecf20Sopenharmony_ci		*npresentp = npresent;
1468c2ecf20Sopenharmony_ci	if (nupp)
1478c2ecf20Sopenharmony_ci		*nupp = nup;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	return nunits;
1508c2ecf20Sopenharmony_ci}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci/**
1538c2ecf20Sopenharmony_ci * qib_wait_linkstate - wait for an IB link state change to occur
1548c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device
1558c2ecf20Sopenharmony_ci * @state: the state to wait for
1568c2ecf20Sopenharmony_ci * @msecs: the number of milliseconds to wait
1578c2ecf20Sopenharmony_ci *
1588c2ecf20Sopenharmony_ci * wait up to msecs milliseconds for IB link state change to occur for
1598c2ecf20Sopenharmony_ci * now, take the easy polling route.  Currently used only by
1608c2ecf20Sopenharmony_ci * qib_set_linkstate.  Returns 0 if state reached, otherwise
1618c2ecf20Sopenharmony_ci * -ETIMEDOUT state can have multiple states set, for any of several
1628c2ecf20Sopenharmony_ci * transitions.
1638c2ecf20Sopenharmony_ci */
1648c2ecf20Sopenharmony_ciint qib_wait_linkstate(struct qib_pportdata *ppd, u32 state, int msecs)
1658c2ecf20Sopenharmony_ci{
1668c2ecf20Sopenharmony_ci	int ret;
1678c2ecf20Sopenharmony_ci	unsigned long flags;
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ppd->lflags_lock, flags);
1708c2ecf20Sopenharmony_ci	if (ppd->state_wanted) {
1718c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
1728c2ecf20Sopenharmony_ci		ret = -EBUSY;
1738c2ecf20Sopenharmony_ci		goto bail;
1748c2ecf20Sopenharmony_ci	}
1758c2ecf20Sopenharmony_ci	ppd->state_wanted = state;
1768c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ppd->lflags_lock, flags);
1778c2ecf20Sopenharmony_ci	wait_event_interruptible_timeout(ppd->state_wait,
1788c2ecf20Sopenharmony_ci					 (ppd->lflags & state),
1798c2ecf20Sopenharmony_ci					 msecs_to_jiffies(msecs));
1808c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ppd->lflags_lock, flags);
1818c2ecf20Sopenharmony_ci	ppd->state_wanted = 0;
1828c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ppd->lflags_lock, flags);
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	if (!(ppd->lflags & state))
1858c2ecf20Sopenharmony_ci		ret = -ETIMEDOUT;
1868c2ecf20Sopenharmony_ci	else
1878c2ecf20Sopenharmony_ci		ret = 0;
1888c2ecf20Sopenharmony_cibail:
1898c2ecf20Sopenharmony_ci	return ret;
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ciint qib_set_linkstate(struct qib_pportdata *ppd, u8 newstate)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	u32 lstate;
1958c2ecf20Sopenharmony_ci	int ret;
1968c2ecf20Sopenharmony_ci	struct qib_devdata *dd = ppd->dd;
1978c2ecf20Sopenharmony_ci	unsigned long flags;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	switch (newstate) {
2008c2ecf20Sopenharmony_ci	case QIB_IB_LINKDOWN_ONLY:
2018c2ecf20Sopenharmony_ci		dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE,
2028c2ecf20Sopenharmony_ci				 IB_LINKCMD_DOWN | IB_LINKINITCMD_NOP);
2038c2ecf20Sopenharmony_ci		/* don't wait */
2048c2ecf20Sopenharmony_ci		ret = 0;
2058c2ecf20Sopenharmony_ci		goto bail;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	case QIB_IB_LINKDOWN:
2088c2ecf20Sopenharmony_ci		dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE,
2098c2ecf20Sopenharmony_ci				 IB_LINKCMD_DOWN | IB_LINKINITCMD_POLL);
2108c2ecf20Sopenharmony_ci		/* don't wait */
2118c2ecf20Sopenharmony_ci		ret = 0;
2128c2ecf20Sopenharmony_ci		goto bail;
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	case QIB_IB_LINKDOWN_SLEEP:
2158c2ecf20Sopenharmony_ci		dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE,
2168c2ecf20Sopenharmony_ci				 IB_LINKCMD_DOWN | IB_LINKINITCMD_SLEEP);
2178c2ecf20Sopenharmony_ci		/* don't wait */
2188c2ecf20Sopenharmony_ci		ret = 0;
2198c2ecf20Sopenharmony_ci		goto bail;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	case QIB_IB_LINKDOWN_DISABLE:
2228c2ecf20Sopenharmony_ci		dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE,
2238c2ecf20Sopenharmony_ci				 IB_LINKCMD_DOWN | IB_LINKINITCMD_DISABLE);
2248c2ecf20Sopenharmony_ci		/* don't wait */
2258c2ecf20Sopenharmony_ci		ret = 0;
2268c2ecf20Sopenharmony_ci		goto bail;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	case QIB_IB_LINKARM:
2298c2ecf20Sopenharmony_ci		if (ppd->lflags & QIBL_LINKARMED) {
2308c2ecf20Sopenharmony_ci			ret = 0;
2318c2ecf20Sopenharmony_ci			goto bail;
2328c2ecf20Sopenharmony_ci		}
2338c2ecf20Sopenharmony_ci		if (!(ppd->lflags & (QIBL_LINKINIT | QIBL_LINKACTIVE))) {
2348c2ecf20Sopenharmony_ci			ret = -EINVAL;
2358c2ecf20Sopenharmony_ci			goto bail;
2368c2ecf20Sopenharmony_ci		}
2378c2ecf20Sopenharmony_ci		/*
2388c2ecf20Sopenharmony_ci		 * Since the port can be ACTIVE when we ask for ARMED,
2398c2ecf20Sopenharmony_ci		 * clear QIBL_LINKV so we can wait for a transition.
2408c2ecf20Sopenharmony_ci		 * If the link isn't ARMED, then something else happened
2418c2ecf20Sopenharmony_ci		 * and there is no point waiting for ARMED.
2428c2ecf20Sopenharmony_ci		 */
2438c2ecf20Sopenharmony_ci		spin_lock_irqsave(&ppd->lflags_lock, flags);
2448c2ecf20Sopenharmony_ci		ppd->lflags &= ~QIBL_LINKV;
2458c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
2468c2ecf20Sopenharmony_ci		dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE,
2478c2ecf20Sopenharmony_ci				 IB_LINKCMD_ARMED | IB_LINKINITCMD_NOP);
2488c2ecf20Sopenharmony_ci		lstate = QIBL_LINKV;
2498c2ecf20Sopenharmony_ci		break;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	case QIB_IB_LINKACTIVE:
2528c2ecf20Sopenharmony_ci		if (ppd->lflags & QIBL_LINKACTIVE) {
2538c2ecf20Sopenharmony_ci			ret = 0;
2548c2ecf20Sopenharmony_ci			goto bail;
2558c2ecf20Sopenharmony_ci		}
2568c2ecf20Sopenharmony_ci		if (!(ppd->lflags & QIBL_LINKARMED)) {
2578c2ecf20Sopenharmony_ci			ret = -EINVAL;
2588c2ecf20Sopenharmony_ci			goto bail;
2598c2ecf20Sopenharmony_ci		}
2608c2ecf20Sopenharmony_ci		dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE,
2618c2ecf20Sopenharmony_ci				 IB_LINKCMD_ACTIVE | IB_LINKINITCMD_NOP);
2628c2ecf20Sopenharmony_ci		lstate = QIBL_LINKACTIVE;
2638c2ecf20Sopenharmony_ci		break;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	default:
2668c2ecf20Sopenharmony_ci		ret = -EINVAL;
2678c2ecf20Sopenharmony_ci		goto bail;
2688c2ecf20Sopenharmony_ci	}
2698c2ecf20Sopenharmony_ci	ret = qib_wait_linkstate(ppd, lstate, 10);
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_cibail:
2728c2ecf20Sopenharmony_ci	return ret;
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci/*
2768c2ecf20Sopenharmony_ci * Get address of eager buffer from it's index (allocated in chunks, not
2778c2ecf20Sopenharmony_ci * contiguous).
2788c2ecf20Sopenharmony_ci */
2798c2ecf20Sopenharmony_cistatic inline void *qib_get_egrbuf(const struct qib_ctxtdata *rcd, u32 etail)
2808c2ecf20Sopenharmony_ci{
2818c2ecf20Sopenharmony_ci	const u32 chunk = etail >> rcd->rcvegrbufs_perchunk_shift;
2828c2ecf20Sopenharmony_ci	const u32 idx =  etail & ((u32)rcd->rcvegrbufs_perchunk - 1);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	return rcd->rcvegrbuf[chunk] + (idx << rcd->dd->rcvegrbufsize_shift);
2858c2ecf20Sopenharmony_ci}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci/*
2888c2ecf20Sopenharmony_ci * Returns 1 if error was a CRC, else 0.
2898c2ecf20Sopenharmony_ci * Needed for some chip's synthesized error counters.
2908c2ecf20Sopenharmony_ci */
2918c2ecf20Sopenharmony_cistatic u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
2928c2ecf20Sopenharmony_ci			  u32 ctxt, u32 eflags, u32 l, u32 etail,
2938c2ecf20Sopenharmony_ci			  __le32 *rhf_addr, struct qib_message_header *rhdr)
2948c2ecf20Sopenharmony_ci{
2958c2ecf20Sopenharmony_ci	u32 ret = 0;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	if (eflags & (QLOGIC_IB_RHF_H_ICRCERR | QLOGIC_IB_RHF_H_VCRCERR))
2988c2ecf20Sopenharmony_ci		ret = 1;
2998c2ecf20Sopenharmony_ci	else if (eflags == QLOGIC_IB_RHF_H_TIDERR) {
3008c2ecf20Sopenharmony_ci		/* For TIDERR and RC QPs premptively schedule a NAK */
3018c2ecf20Sopenharmony_ci		struct ib_header *hdr = (struct ib_header *)rhdr;
3028c2ecf20Sopenharmony_ci		struct ib_other_headers *ohdr = NULL;
3038c2ecf20Sopenharmony_ci		struct qib_ibport *ibp = &ppd->ibport_data;
3048c2ecf20Sopenharmony_ci		struct qib_devdata *dd = ppd->dd;
3058c2ecf20Sopenharmony_ci		struct rvt_dev_info *rdi = &dd->verbs_dev.rdi;
3068c2ecf20Sopenharmony_ci		struct rvt_qp *qp = NULL;
3078c2ecf20Sopenharmony_ci		u32 tlen = qib_hdrget_length_in_bytes(rhf_addr);
3088c2ecf20Sopenharmony_ci		u16 lid  = be16_to_cpu(hdr->lrh[1]);
3098c2ecf20Sopenharmony_ci		int lnh = be16_to_cpu(hdr->lrh[0]) & 3;
3108c2ecf20Sopenharmony_ci		u32 qp_num;
3118c2ecf20Sopenharmony_ci		u32 opcode;
3128c2ecf20Sopenharmony_ci		u32 psn;
3138c2ecf20Sopenharmony_ci		int diff;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci		/* Sanity check packet */
3168c2ecf20Sopenharmony_ci		if (tlen < 24)
3178c2ecf20Sopenharmony_ci			goto drop;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci		if (lid < be16_to_cpu(IB_MULTICAST_LID_BASE)) {
3208c2ecf20Sopenharmony_ci			lid &= ~((1 << ppd->lmc) - 1);
3218c2ecf20Sopenharmony_ci			if (unlikely(lid != ppd->lid))
3228c2ecf20Sopenharmony_ci				goto drop;
3238c2ecf20Sopenharmony_ci		}
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci		/* Check for GRH */
3268c2ecf20Sopenharmony_ci		if (lnh == QIB_LRH_BTH)
3278c2ecf20Sopenharmony_ci			ohdr = &hdr->u.oth;
3288c2ecf20Sopenharmony_ci		else if (lnh == QIB_LRH_GRH) {
3298c2ecf20Sopenharmony_ci			u32 vtf;
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci			ohdr = &hdr->u.l.oth;
3328c2ecf20Sopenharmony_ci			if (hdr->u.l.grh.next_hdr != IB_GRH_NEXT_HDR)
3338c2ecf20Sopenharmony_ci				goto drop;
3348c2ecf20Sopenharmony_ci			vtf = be32_to_cpu(hdr->u.l.grh.version_tclass_flow);
3358c2ecf20Sopenharmony_ci			if ((vtf >> IB_GRH_VERSION_SHIFT) != IB_GRH_VERSION)
3368c2ecf20Sopenharmony_ci				goto drop;
3378c2ecf20Sopenharmony_ci		} else
3388c2ecf20Sopenharmony_ci			goto drop;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci		/* Get opcode and PSN from packet */
3418c2ecf20Sopenharmony_ci		opcode = be32_to_cpu(ohdr->bth[0]);
3428c2ecf20Sopenharmony_ci		opcode >>= 24;
3438c2ecf20Sopenharmony_ci		psn = be32_to_cpu(ohdr->bth[2]);
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci		/* Get the destination QP number. */
3468c2ecf20Sopenharmony_ci		qp_num = be32_to_cpu(ohdr->bth[1]) & RVT_QPN_MASK;
3478c2ecf20Sopenharmony_ci		if (qp_num != QIB_MULTICAST_QPN) {
3488c2ecf20Sopenharmony_ci			int ruc_res;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci			rcu_read_lock();
3518c2ecf20Sopenharmony_ci			qp = rvt_lookup_qpn(rdi, &ibp->rvp, qp_num);
3528c2ecf20Sopenharmony_ci			if (!qp) {
3538c2ecf20Sopenharmony_ci				rcu_read_unlock();
3548c2ecf20Sopenharmony_ci				goto drop;
3558c2ecf20Sopenharmony_ci			}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci			/*
3588c2ecf20Sopenharmony_ci			 * Handle only RC QPs - for other QP types drop error
3598c2ecf20Sopenharmony_ci			 * packet.
3608c2ecf20Sopenharmony_ci			 */
3618c2ecf20Sopenharmony_ci			spin_lock(&qp->r_lock);
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci			/* Check for valid receive state. */
3648c2ecf20Sopenharmony_ci			if (!(ib_rvt_state_ops[qp->state] &
3658c2ecf20Sopenharmony_ci			      RVT_PROCESS_RECV_OK)) {
3668c2ecf20Sopenharmony_ci				ibp->rvp.n_pkt_drops++;
3678c2ecf20Sopenharmony_ci				goto unlock;
3688c2ecf20Sopenharmony_ci			}
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci			switch (qp->ibqp.qp_type) {
3718c2ecf20Sopenharmony_ci			case IB_QPT_RC:
3728c2ecf20Sopenharmony_ci				ruc_res =
3738c2ecf20Sopenharmony_ci					qib_ruc_check_hdr(
3748c2ecf20Sopenharmony_ci						ibp, hdr,
3758c2ecf20Sopenharmony_ci						lnh == QIB_LRH_GRH,
3768c2ecf20Sopenharmony_ci						qp,
3778c2ecf20Sopenharmony_ci						be32_to_cpu(ohdr->bth[0]));
3788c2ecf20Sopenharmony_ci				if (ruc_res)
3798c2ecf20Sopenharmony_ci					goto unlock;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci				/* Only deal with RDMA Writes for now */
3828c2ecf20Sopenharmony_ci				if (opcode <
3838c2ecf20Sopenharmony_ci				    IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST) {
3848c2ecf20Sopenharmony_ci					diff = qib_cmp24(psn, qp->r_psn);
3858c2ecf20Sopenharmony_ci					if (!qp->r_nak_state && diff >= 0) {
3868c2ecf20Sopenharmony_ci						ibp->rvp.n_rc_seqnak++;
3878c2ecf20Sopenharmony_ci						qp->r_nak_state =
3888c2ecf20Sopenharmony_ci							IB_NAK_PSN_ERROR;
3898c2ecf20Sopenharmony_ci						/* Use the expected PSN. */
3908c2ecf20Sopenharmony_ci						qp->r_ack_psn = qp->r_psn;
3918c2ecf20Sopenharmony_ci						/*
3928c2ecf20Sopenharmony_ci						 * Wait to send the sequence
3938c2ecf20Sopenharmony_ci						 * NAK until all packets
3948c2ecf20Sopenharmony_ci						 * in the receive queue have
3958c2ecf20Sopenharmony_ci						 * been processed.
3968c2ecf20Sopenharmony_ci						 * Otherwise, we end up
3978c2ecf20Sopenharmony_ci						 * propagating congestion.
3988c2ecf20Sopenharmony_ci						 */
3998c2ecf20Sopenharmony_ci						if (list_empty(&qp->rspwait)) {
4008c2ecf20Sopenharmony_ci							qp->r_flags |=
4018c2ecf20Sopenharmony_ci								RVT_R_RSP_NAK;
4028c2ecf20Sopenharmony_ci							rvt_get_qp(qp);
4038c2ecf20Sopenharmony_ci							list_add_tail(
4048c2ecf20Sopenharmony_ci							 &qp->rspwait,
4058c2ecf20Sopenharmony_ci							 &rcd->qp_wait_list);
4068c2ecf20Sopenharmony_ci						}
4078c2ecf20Sopenharmony_ci					} /* Out of sequence NAK */
4088c2ecf20Sopenharmony_ci				} /* QP Request NAKs */
4098c2ecf20Sopenharmony_ci				break;
4108c2ecf20Sopenharmony_ci			case IB_QPT_SMI:
4118c2ecf20Sopenharmony_ci			case IB_QPT_GSI:
4128c2ecf20Sopenharmony_ci			case IB_QPT_UD:
4138c2ecf20Sopenharmony_ci			case IB_QPT_UC:
4148c2ecf20Sopenharmony_ci			default:
4158c2ecf20Sopenharmony_ci				/* For now don't handle any other QP types */
4168c2ecf20Sopenharmony_ci				break;
4178c2ecf20Sopenharmony_ci			}
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ciunlock:
4208c2ecf20Sopenharmony_ci			spin_unlock(&qp->r_lock);
4218c2ecf20Sopenharmony_ci			rcu_read_unlock();
4228c2ecf20Sopenharmony_ci		} /* Unicast QP */
4238c2ecf20Sopenharmony_ci	} /* Valid packet with TIDErr */
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_cidrop:
4268c2ecf20Sopenharmony_ci	return ret;
4278c2ecf20Sopenharmony_ci}
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci/*
4308c2ecf20Sopenharmony_ci * qib_kreceive - receive a packet
4318c2ecf20Sopenharmony_ci * @rcd: the qlogic_ib context
4328c2ecf20Sopenharmony_ci * @llic: gets count of good packets needed to clear lli,
4338c2ecf20Sopenharmony_ci *          (used with chips that need need to track crcs for lli)
4348c2ecf20Sopenharmony_ci *
4358c2ecf20Sopenharmony_ci * called from interrupt handler for errors or receive interrupt
4368c2ecf20Sopenharmony_ci * Returns number of CRC error packets, needed by some chips for
4378c2ecf20Sopenharmony_ci * local link integrity tracking.   crcs are adjusted down by following
4388c2ecf20Sopenharmony_ci * good packets, if any, and count of good packets is also tracked.
4398c2ecf20Sopenharmony_ci */
4408c2ecf20Sopenharmony_ciu32 qib_kreceive(struct qib_ctxtdata *rcd, u32 *llic, u32 *npkts)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	struct qib_devdata *dd = rcd->dd;
4438c2ecf20Sopenharmony_ci	struct qib_pportdata *ppd = rcd->ppd;
4448c2ecf20Sopenharmony_ci	__le32 *rhf_addr;
4458c2ecf20Sopenharmony_ci	void *ebuf;
4468c2ecf20Sopenharmony_ci	const u32 rsize = dd->rcvhdrentsize;        /* words */
4478c2ecf20Sopenharmony_ci	const u32 maxcnt = dd->rcvhdrcnt * rsize;   /* words */
4488c2ecf20Sopenharmony_ci	u32 etail = -1, l, hdrqtail;
4498c2ecf20Sopenharmony_ci	struct qib_message_header *hdr;
4508c2ecf20Sopenharmony_ci	u32 eflags, etype, tlen, i = 0, updegr = 0, crcs = 0;
4518c2ecf20Sopenharmony_ci	int last;
4528c2ecf20Sopenharmony_ci	u64 lval;
4538c2ecf20Sopenharmony_ci	struct rvt_qp *qp, *nqp;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	l = rcd->head;
4568c2ecf20Sopenharmony_ci	rhf_addr = (__le32 *) rcd->rcvhdrq + l + dd->rhf_offset;
4578c2ecf20Sopenharmony_ci	if (dd->flags & QIB_NODMA_RTAIL) {
4588c2ecf20Sopenharmony_ci		u32 seq = qib_hdrget_seq(rhf_addr);
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci		if (seq != rcd->seq_cnt)
4618c2ecf20Sopenharmony_ci			goto bail;
4628c2ecf20Sopenharmony_ci		hdrqtail = 0;
4638c2ecf20Sopenharmony_ci	} else {
4648c2ecf20Sopenharmony_ci		hdrqtail = qib_get_rcvhdrtail(rcd);
4658c2ecf20Sopenharmony_ci		if (l == hdrqtail)
4668c2ecf20Sopenharmony_ci			goto bail;
4678c2ecf20Sopenharmony_ci		smp_rmb();  /* prevent speculative reads of dma'ed hdrq */
4688c2ecf20Sopenharmony_ci	}
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	for (last = 0, i = 1; !last; i += !last) {
4718c2ecf20Sopenharmony_ci		hdr = dd->f_get_msgheader(dd, rhf_addr);
4728c2ecf20Sopenharmony_ci		eflags = qib_hdrget_err_flags(rhf_addr);
4738c2ecf20Sopenharmony_ci		etype = qib_hdrget_rcv_type(rhf_addr);
4748c2ecf20Sopenharmony_ci		/* total length */
4758c2ecf20Sopenharmony_ci		tlen = qib_hdrget_length_in_bytes(rhf_addr);
4768c2ecf20Sopenharmony_ci		ebuf = NULL;
4778c2ecf20Sopenharmony_ci		if ((dd->flags & QIB_NODMA_RTAIL) ?
4788c2ecf20Sopenharmony_ci		    qib_hdrget_use_egr_buf(rhf_addr) :
4798c2ecf20Sopenharmony_ci		    (etype != RCVHQ_RCV_TYPE_EXPECTED)) {
4808c2ecf20Sopenharmony_ci			etail = qib_hdrget_index(rhf_addr);
4818c2ecf20Sopenharmony_ci			updegr = 1;
4828c2ecf20Sopenharmony_ci			if (tlen > sizeof(*hdr) ||
4838c2ecf20Sopenharmony_ci			    etype >= RCVHQ_RCV_TYPE_NON_KD) {
4848c2ecf20Sopenharmony_ci				ebuf = qib_get_egrbuf(rcd, etail);
4858c2ecf20Sopenharmony_ci				prefetch_range(ebuf, tlen - sizeof(*hdr));
4868c2ecf20Sopenharmony_ci			}
4878c2ecf20Sopenharmony_ci		}
4888c2ecf20Sopenharmony_ci		if (!eflags) {
4898c2ecf20Sopenharmony_ci			u16 lrh_len = be16_to_cpu(hdr->lrh[2]) << 2;
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci			if (lrh_len != tlen) {
4928c2ecf20Sopenharmony_ci				qib_stats.sps_lenerrs++;
4938c2ecf20Sopenharmony_ci				goto move_along;
4948c2ecf20Sopenharmony_ci			}
4958c2ecf20Sopenharmony_ci		}
4968c2ecf20Sopenharmony_ci		if (etype == RCVHQ_RCV_TYPE_NON_KD && !eflags &&
4978c2ecf20Sopenharmony_ci		    ebuf == NULL &&
4988c2ecf20Sopenharmony_ci		    tlen > (dd->rcvhdrentsize - 2 + 1 -
4998c2ecf20Sopenharmony_ci				qib_hdrget_offset(rhf_addr)) << 2) {
5008c2ecf20Sopenharmony_ci			goto move_along;
5018c2ecf20Sopenharmony_ci		}
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci		/*
5048c2ecf20Sopenharmony_ci		 * Both tiderr and qibhdrerr are set for all plain IB
5058c2ecf20Sopenharmony_ci		 * packets; only qibhdrerr should be set.
5068c2ecf20Sopenharmony_ci		 */
5078c2ecf20Sopenharmony_ci		if (unlikely(eflags))
5088c2ecf20Sopenharmony_ci			crcs += qib_rcv_hdrerr(rcd, ppd, rcd->ctxt, eflags, l,
5098c2ecf20Sopenharmony_ci					       etail, rhf_addr, hdr);
5108c2ecf20Sopenharmony_ci		else if (etype == RCVHQ_RCV_TYPE_NON_KD) {
5118c2ecf20Sopenharmony_ci			qib_ib_rcv(rcd, hdr, ebuf, tlen);
5128c2ecf20Sopenharmony_ci			if (crcs)
5138c2ecf20Sopenharmony_ci				crcs--;
5148c2ecf20Sopenharmony_ci			else if (llic && *llic)
5158c2ecf20Sopenharmony_ci				--*llic;
5168c2ecf20Sopenharmony_ci		}
5178c2ecf20Sopenharmony_cimove_along:
5188c2ecf20Sopenharmony_ci		l += rsize;
5198c2ecf20Sopenharmony_ci		if (l >= maxcnt)
5208c2ecf20Sopenharmony_ci			l = 0;
5218c2ecf20Sopenharmony_ci		if (i == QIB_MAX_PKT_RECV)
5228c2ecf20Sopenharmony_ci			last = 1;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci		rhf_addr = (__le32 *) rcd->rcvhdrq + l + dd->rhf_offset;
5258c2ecf20Sopenharmony_ci		if (dd->flags & QIB_NODMA_RTAIL) {
5268c2ecf20Sopenharmony_ci			u32 seq = qib_hdrget_seq(rhf_addr);
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci			if (++rcd->seq_cnt > 13)
5298c2ecf20Sopenharmony_ci				rcd->seq_cnt = 1;
5308c2ecf20Sopenharmony_ci			if (seq != rcd->seq_cnt)
5318c2ecf20Sopenharmony_ci				last = 1;
5328c2ecf20Sopenharmony_ci		} else if (l == hdrqtail)
5338c2ecf20Sopenharmony_ci			last = 1;
5348c2ecf20Sopenharmony_ci		/*
5358c2ecf20Sopenharmony_ci		 * Update head regs etc., every 16 packets, if not last pkt,
5368c2ecf20Sopenharmony_ci		 * to help prevent rcvhdrq overflows, when many packets
5378c2ecf20Sopenharmony_ci		 * are processed and queue is nearly full.
5388c2ecf20Sopenharmony_ci		 * Don't request an interrupt for intermediate updates.
5398c2ecf20Sopenharmony_ci		 */
5408c2ecf20Sopenharmony_ci		lval = l;
5418c2ecf20Sopenharmony_ci		if (!last && !(i & 0xf)) {
5428c2ecf20Sopenharmony_ci			dd->f_update_usrhead(rcd, lval, updegr, etail, i);
5438c2ecf20Sopenharmony_ci			updegr = 0;
5448c2ecf20Sopenharmony_ci		}
5458c2ecf20Sopenharmony_ci	}
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	rcd->head = l;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	/*
5508c2ecf20Sopenharmony_ci	 * Iterate over all QPs waiting to respond.
5518c2ecf20Sopenharmony_ci	 * The list won't change since the IRQ is only run on one CPU.
5528c2ecf20Sopenharmony_ci	 */
5538c2ecf20Sopenharmony_ci	list_for_each_entry_safe(qp, nqp, &rcd->qp_wait_list, rspwait) {
5548c2ecf20Sopenharmony_ci		list_del_init(&qp->rspwait);
5558c2ecf20Sopenharmony_ci		if (qp->r_flags & RVT_R_RSP_NAK) {
5568c2ecf20Sopenharmony_ci			qp->r_flags &= ~RVT_R_RSP_NAK;
5578c2ecf20Sopenharmony_ci			qib_send_rc_ack(qp);
5588c2ecf20Sopenharmony_ci		}
5598c2ecf20Sopenharmony_ci		if (qp->r_flags & RVT_R_RSP_SEND) {
5608c2ecf20Sopenharmony_ci			unsigned long flags;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci			qp->r_flags &= ~RVT_R_RSP_SEND;
5638c2ecf20Sopenharmony_ci			spin_lock_irqsave(&qp->s_lock, flags);
5648c2ecf20Sopenharmony_ci			if (ib_rvt_state_ops[qp->state] &
5658c2ecf20Sopenharmony_ci					RVT_PROCESS_OR_FLUSH_SEND)
5668c2ecf20Sopenharmony_ci				qib_schedule_send(qp);
5678c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&qp->s_lock, flags);
5688c2ecf20Sopenharmony_ci		}
5698c2ecf20Sopenharmony_ci		rvt_put_qp(qp);
5708c2ecf20Sopenharmony_ci	}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_cibail:
5738c2ecf20Sopenharmony_ci	/* Report number of packets consumed */
5748c2ecf20Sopenharmony_ci	if (npkts)
5758c2ecf20Sopenharmony_ci		*npkts = i;
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	/*
5788c2ecf20Sopenharmony_ci	 * Always write head at end, and setup rcv interrupt, even
5798c2ecf20Sopenharmony_ci	 * if no packets were processed.
5808c2ecf20Sopenharmony_ci	 */
5818c2ecf20Sopenharmony_ci	lval = (u64)rcd->head | dd->rhdrhead_intr_off;
5828c2ecf20Sopenharmony_ci	dd->f_update_usrhead(rcd, lval, updegr, etail, i);
5838c2ecf20Sopenharmony_ci	return crcs;
5848c2ecf20Sopenharmony_ci}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci/**
5878c2ecf20Sopenharmony_ci * qib_set_mtu - set the MTU
5888c2ecf20Sopenharmony_ci * @ppd: the perport data
5898c2ecf20Sopenharmony_ci * @arg: the new MTU
5908c2ecf20Sopenharmony_ci *
5918c2ecf20Sopenharmony_ci * We can handle "any" incoming size, the issue here is whether we
5928c2ecf20Sopenharmony_ci * need to restrict our outgoing size.   For now, we don't do any
5938c2ecf20Sopenharmony_ci * sanity checking on this, and we don't deal with what happens to
5948c2ecf20Sopenharmony_ci * programs that are already running when the size changes.
5958c2ecf20Sopenharmony_ci * NOTE: changing the MTU will usually cause the IBC to go back to
5968c2ecf20Sopenharmony_ci * link INIT state...
5978c2ecf20Sopenharmony_ci */
5988c2ecf20Sopenharmony_ciint qib_set_mtu(struct qib_pportdata *ppd, u16 arg)
5998c2ecf20Sopenharmony_ci{
6008c2ecf20Sopenharmony_ci	u32 piosize;
6018c2ecf20Sopenharmony_ci	int ret, chk;
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	if (arg != 256 && arg != 512 && arg != 1024 && arg != 2048 &&
6048c2ecf20Sopenharmony_ci	    arg != 4096) {
6058c2ecf20Sopenharmony_ci		ret = -EINVAL;
6068c2ecf20Sopenharmony_ci		goto bail;
6078c2ecf20Sopenharmony_ci	}
6088c2ecf20Sopenharmony_ci	chk = ib_mtu_enum_to_int(qib_ibmtu);
6098c2ecf20Sopenharmony_ci	if (chk > 0 && arg > chk) {
6108c2ecf20Sopenharmony_ci		ret = -EINVAL;
6118c2ecf20Sopenharmony_ci		goto bail;
6128c2ecf20Sopenharmony_ci	}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	piosize = ppd->ibmaxlen;
6158c2ecf20Sopenharmony_ci	ppd->ibmtu = arg;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	if (arg >= (piosize - QIB_PIO_MAXIBHDR)) {
6188c2ecf20Sopenharmony_ci		/* Only if it's not the initial value (or reset to it) */
6198c2ecf20Sopenharmony_ci		if (piosize != ppd->init_ibmaxlen) {
6208c2ecf20Sopenharmony_ci			if (arg > piosize && arg <= ppd->init_ibmaxlen)
6218c2ecf20Sopenharmony_ci				piosize = ppd->init_ibmaxlen - 2 * sizeof(u32);
6228c2ecf20Sopenharmony_ci			ppd->ibmaxlen = piosize;
6238c2ecf20Sopenharmony_ci		}
6248c2ecf20Sopenharmony_ci	} else if ((arg + QIB_PIO_MAXIBHDR) != ppd->ibmaxlen) {
6258c2ecf20Sopenharmony_ci		piosize = arg + QIB_PIO_MAXIBHDR - 2 * sizeof(u32);
6268c2ecf20Sopenharmony_ci		ppd->ibmaxlen = piosize;
6278c2ecf20Sopenharmony_ci	}
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	ppd->dd->f_set_ib_cfg(ppd, QIB_IB_CFG_MTU, 0);
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	ret = 0;
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_cibail:
6348c2ecf20Sopenharmony_ci	return ret;
6358c2ecf20Sopenharmony_ci}
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ciint qib_set_lid(struct qib_pportdata *ppd, u32 lid, u8 lmc)
6388c2ecf20Sopenharmony_ci{
6398c2ecf20Sopenharmony_ci	struct qib_devdata *dd = ppd->dd;
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	ppd->lid = lid;
6428c2ecf20Sopenharmony_ci	ppd->lmc = lmc;
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LIDLMC,
6458c2ecf20Sopenharmony_ci			 lid | (~((1U << lmc) - 1)) << 16);
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	qib_devinfo(dd->pcidev, "IB%u:%u got a lid: 0x%x\n",
6488c2ecf20Sopenharmony_ci		    dd->unit, ppd->port, lid);
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	return 0;
6518c2ecf20Sopenharmony_ci}
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci/*
6548c2ecf20Sopenharmony_ci * Following deal with the "obviously simple" task of overriding the state
6558c2ecf20Sopenharmony_ci * of the LEDS, which normally indicate link physical and logical status.
6568c2ecf20Sopenharmony_ci * The complications arise in dealing with different hardware mappings
6578c2ecf20Sopenharmony_ci * and the board-dependent routine being called from interrupts.
6588c2ecf20Sopenharmony_ci * and then there's the requirement to _flash_ them.
6598c2ecf20Sopenharmony_ci */
6608c2ecf20Sopenharmony_ci#define LED_OVER_FREQ_SHIFT 8
6618c2ecf20Sopenharmony_ci#define LED_OVER_FREQ_MASK (0xFF<<LED_OVER_FREQ_SHIFT)
6628c2ecf20Sopenharmony_ci/* Below is "non-zero" to force override, but both actual LEDs are off */
6638c2ecf20Sopenharmony_ci#define LED_OVER_BOTH_OFF (8)
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_cistatic void qib_run_led_override(struct timer_list *t)
6668c2ecf20Sopenharmony_ci{
6678c2ecf20Sopenharmony_ci	struct qib_pportdata *ppd = from_timer(ppd, t,
6688c2ecf20Sopenharmony_ci						    led_override_timer);
6698c2ecf20Sopenharmony_ci	struct qib_devdata *dd = ppd->dd;
6708c2ecf20Sopenharmony_ci	int timeoff;
6718c2ecf20Sopenharmony_ci	int ph_idx;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	if (!(dd->flags & QIB_INITTED))
6748c2ecf20Sopenharmony_ci		return;
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci	ph_idx = ppd->led_override_phase++ & 1;
6778c2ecf20Sopenharmony_ci	ppd->led_override = ppd->led_override_vals[ph_idx];
6788c2ecf20Sopenharmony_ci	timeoff = ppd->led_override_timeoff;
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	dd->f_setextled(ppd, 1);
6818c2ecf20Sopenharmony_ci	/*
6828c2ecf20Sopenharmony_ci	 * don't re-fire the timer if user asked for it to be off; we let
6838c2ecf20Sopenharmony_ci	 * it fire one more time after they turn it off to simplify
6848c2ecf20Sopenharmony_ci	 */
6858c2ecf20Sopenharmony_ci	if (ppd->led_override_vals[0] || ppd->led_override_vals[1])
6868c2ecf20Sopenharmony_ci		mod_timer(&ppd->led_override_timer, jiffies + timeoff);
6878c2ecf20Sopenharmony_ci}
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_civoid qib_set_led_override(struct qib_pportdata *ppd, unsigned int val)
6908c2ecf20Sopenharmony_ci{
6918c2ecf20Sopenharmony_ci	struct qib_devdata *dd = ppd->dd;
6928c2ecf20Sopenharmony_ci	int timeoff, freq;
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	if (!(dd->flags & QIB_INITTED))
6958c2ecf20Sopenharmony_ci		return;
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	/* First check if we are blinking. If not, use 1HZ polling */
6988c2ecf20Sopenharmony_ci	timeoff = HZ;
6998c2ecf20Sopenharmony_ci	freq = (val & LED_OVER_FREQ_MASK) >> LED_OVER_FREQ_SHIFT;
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	if (freq) {
7028c2ecf20Sopenharmony_ci		/* For blink, set each phase from one nybble of val */
7038c2ecf20Sopenharmony_ci		ppd->led_override_vals[0] = val & 0xF;
7048c2ecf20Sopenharmony_ci		ppd->led_override_vals[1] = (val >> 4) & 0xF;
7058c2ecf20Sopenharmony_ci		timeoff = (HZ << 4)/freq;
7068c2ecf20Sopenharmony_ci	} else {
7078c2ecf20Sopenharmony_ci		/* Non-blink set both phases the same. */
7088c2ecf20Sopenharmony_ci		ppd->led_override_vals[0] = val & 0xF;
7098c2ecf20Sopenharmony_ci		ppd->led_override_vals[1] = val & 0xF;
7108c2ecf20Sopenharmony_ci	}
7118c2ecf20Sopenharmony_ci	ppd->led_override_timeoff = timeoff;
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	/*
7148c2ecf20Sopenharmony_ci	 * If the timer has not already been started, do so. Use a "quick"
7158c2ecf20Sopenharmony_ci	 * timeout so the function will be called soon, to look at our request.
7168c2ecf20Sopenharmony_ci	 */
7178c2ecf20Sopenharmony_ci	if (atomic_inc_return(&ppd->led_override_timer_active) == 1) {
7188c2ecf20Sopenharmony_ci		/* Need to start timer */
7198c2ecf20Sopenharmony_ci		timer_setup(&ppd->led_override_timer, qib_run_led_override, 0);
7208c2ecf20Sopenharmony_ci		ppd->led_override_timer.expires = jiffies + 1;
7218c2ecf20Sopenharmony_ci		add_timer(&ppd->led_override_timer);
7228c2ecf20Sopenharmony_ci	} else {
7238c2ecf20Sopenharmony_ci		if (ppd->led_override_vals[0] || ppd->led_override_vals[1])
7248c2ecf20Sopenharmony_ci			mod_timer(&ppd->led_override_timer, jiffies + 1);
7258c2ecf20Sopenharmony_ci		atomic_dec(&ppd->led_override_timer_active);
7268c2ecf20Sopenharmony_ci	}
7278c2ecf20Sopenharmony_ci}
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci/**
7308c2ecf20Sopenharmony_ci * qib_reset_device - reset the chip if possible
7318c2ecf20Sopenharmony_ci * @unit: the device to reset
7328c2ecf20Sopenharmony_ci *
7338c2ecf20Sopenharmony_ci * Whether or not reset is successful, we attempt to re-initialize the chip
7348c2ecf20Sopenharmony_ci * (that is, much like a driver unload/reload).  We clear the INITTED flag
7358c2ecf20Sopenharmony_ci * so that the various entry points will fail until we reinitialize.  For
7368c2ecf20Sopenharmony_ci * now, we only allow this if no user contexts are open that use chip resources
7378c2ecf20Sopenharmony_ci */
7388c2ecf20Sopenharmony_ciint qib_reset_device(int unit)
7398c2ecf20Sopenharmony_ci{
7408c2ecf20Sopenharmony_ci	int ret, i;
7418c2ecf20Sopenharmony_ci	struct qib_devdata *dd = qib_lookup(unit);
7428c2ecf20Sopenharmony_ci	struct qib_pportdata *ppd;
7438c2ecf20Sopenharmony_ci	unsigned long flags;
7448c2ecf20Sopenharmony_ci	int pidx;
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	if (!dd) {
7478c2ecf20Sopenharmony_ci		ret = -ENODEV;
7488c2ecf20Sopenharmony_ci		goto bail;
7498c2ecf20Sopenharmony_ci	}
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	qib_devinfo(dd->pcidev, "Reset on unit %u requested\n", unit);
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	if (!dd->kregbase || !(dd->flags & QIB_PRESENT)) {
7548c2ecf20Sopenharmony_ci		qib_devinfo(dd->pcidev,
7558c2ecf20Sopenharmony_ci			"Invalid unit number %u or not initialized or not present\n",
7568c2ecf20Sopenharmony_ci			unit);
7578c2ecf20Sopenharmony_ci		ret = -ENXIO;
7588c2ecf20Sopenharmony_ci		goto bail;
7598c2ecf20Sopenharmony_ci	}
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	spin_lock_irqsave(&dd->uctxt_lock, flags);
7628c2ecf20Sopenharmony_ci	if (dd->rcd)
7638c2ecf20Sopenharmony_ci		for (i = dd->first_user_ctxt; i < dd->cfgctxts; i++) {
7648c2ecf20Sopenharmony_ci			if (!dd->rcd[i] || !dd->rcd[i]->cnt)
7658c2ecf20Sopenharmony_ci				continue;
7668c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&dd->uctxt_lock, flags);
7678c2ecf20Sopenharmony_ci			ret = -EBUSY;
7688c2ecf20Sopenharmony_ci			goto bail;
7698c2ecf20Sopenharmony_ci		}
7708c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&dd->uctxt_lock, flags);
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci	for (pidx = 0; pidx < dd->num_pports; ++pidx) {
7738c2ecf20Sopenharmony_ci		ppd = dd->pport + pidx;
7748c2ecf20Sopenharmony_ci		if (atomic_read(&ppd->led_override_timer_active)) {
7758c2ecf20Sopenharmony_ci			/* Need to stop LED timer, _then_ shut off LEDs */
7768c2ecf20Sopenharmony_ci			del_timer_sync(&ppd->led_override_timer);
7778c2ecf20Sopenharmony_ci			atomic_set(&ppd->led_override_timer_active, 0);
7788c2ecf20Sopenharmony_ci		}
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci		/* Shut off LEDs after we are sure timer is not running */
7818c2ecf20Sopenharmony_ci		ppd->led_override = LED_OVER_BOTH_OFF;
7828c2ecf20Sopenharmony_ci		dd->f_setextled(ppd, 0);
7838c2ecf20Sopenharmony_ci		if (dd->flags & QIB_HAS_SEND_DMA)
7848c2ecf20Sopenharmony_ci			qib_teardown_sdma(ppd);
7858c2ecf20Sopenharmony_ci	}
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	ret = dd->f_reset(dd);
7888c2ecf20Sopenharmony_ci	if (ret == 1)
7898c2ecf20Sopenharmony_ci		ret = qib_init(dd, 1);
7908c2ecf20Sopenharmony_ci	else
7918c2ecf20Sopenharmony_ci		ret = -EAGAIN;
7928c2ecf20Sopenharmony_ci	if (ret)
7938c2ecf20Sopenharmony_ci		qib_dev_err(dd,
7948c2ecf20Sopenharmony_ci			"Reinitialize unit %u after reset failed with %d\n",
7958c2ecf20Sopenharmony_ci			unit, ret);
7968c2ecf20Sopenharmony_ci	else
7978c2ecf20Sopenharmony_ci		qib_devinfo(dd->pcidev,
7988c2ecf20Sopenharmony_ci			"Reinitialized unit %u after resetting\n",
7998c2ecf20Sopenharmony_ci			unit);
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_cibail:
8028c2ecf20Sopenharmony_ci	return ret;
8038c2ecf20Sopenharmony_ci}
804