162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2021 Cornelis Networks. All rights reserved. 362306a36Sopenharmony_ci * Copyright (c) 2013 Intel Corporation. All rights reserved. 462306a36Sopenharmony_ci * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved. 562306a36Sopenharmony_ci * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This software is available to you under a choice of one of two 862306a36Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 962306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 1062306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the 1162306a36Sopenharmony_ci * OpenIB.org BSD license below: 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or 1462306a36Sopenharmony_ci * without modification, are permitted provided that the following 1562306a36Sopenharmony_ci * conditions are met: 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * - Redistributions of source code must retain the above 1862306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 1962306a36Sopenharmony_ci * disclaimer. 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * - Redistributions in binary form must reproduce the above 2262306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 2362306a36Sopenharmony_ci * disclaimer in the documentation and/or other materials 2462306a36Sopenharmony_ci * provided with the distribution. 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2762306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2862306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2962306a36Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 3062306a36Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 3162306a36Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 3262306a36Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 3362306a36Sopenharmony_ci * SOFTWARE. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include <linux/spinlock.h> 3762306a36Sopenharmony_ci#include <linux/pci.h> 3862306a36Sopenharmony_ci#include <linux/io.h> 3962306a36Sopenharmony_ci#include <linux/delay.h> 4062306a36Sopenharmony_ci#include <linux/netdevice.h> 4162306a36Sopenharmony_ci#include <linux/vmalloc.h> 4262306a36Sopenharmony_ci#include <linux/module.h> 4362306a36Sopenharmony_ci#include <linux/prefetch.h> 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#include "qib.h" 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* 4862306a36Sopenharmony_ci * The size has to be longer than this string, so we can append 4962306a36Sopenharmony_ci * board/chip information to it in the init code. 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ciconst char ib_qib_version[] = QIB_DRIVER_VERSION "\n"; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ciDEFINE_MUTEX(qib_mutex); /* general driver use */ 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ciunsigned qib_ibmtu; 5662306a36Sopenharmony_cimodule_param_named(ibmtu, qib_ibmtu, uint, S_IRUGO); 5762306a36Sopenharmony_ciMODULE_PARM_DESC(ibmtu, "Set max IB MTU (0=2KB, 1=256, 2=512, ... 5=4096"); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciunsigned qib_compat_ddr_negotiate = 1; 6062306a36Sopenharmony_cimodule_param_named(compat_ddr_negotiate, qib_compat_ddr_negotiate, uint, 6162306a36Sopenharmony_ci S_IWUSR | S_IRUGO); 6262306a36Sopenharmony_ciMODULE_PARM_DESC(compat_ddr_negotiate, 6362306a36Sopenharmony_ci "Attempt pre-IBTA 1.2 DDR speed negotiation"); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 6662306a36Sopenharmony_ciMODULE_AUTHOR("Cornelis <support@cornelisnetworks.com>"); 6762306a36Sopenharmony_ciMODULE_DESCRIPTION("Cornelis IB driver"); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/* 7062306a36Sopenharmony_ci * QIB_PIO_MAXIBHDR is the max IB header size allowed for in our 7162306a36Sopenharmony_ci * PIO send buffers. This is well beyond anything currently 7262306a36Sopenharmony_ci * defined in the InfiniBand spec. 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_ci#define QIB_PIO_MAXIBHDR 128 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/* 7762306a36Sopenharmony_ci * QIB_MAX_PKT_RCV is the max # if packets processed per receive interrupt. 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_ci#define QIB_MAX_PKT_RECV 64 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistruct qlogic_ib_stats qib_stats; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistruct pci_dev *qib_get_pci_dev(struct rvt_dev_info *rdi) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci struct qib_ibdev *ibdev = container_of(rdi, struct qib_ibdev, rdi); 8662306a36Sopenharmony_ci struct qib_devdata *dd = container_of(ibdev, 8762306a36Sopenharmony_ci struct qib_devdata, verbs_dev); 8862306a36Sopenharmony_ci return dd->pcidev; 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/* 9262306a36Sopenharmony_ci * Return count of units with at least one port ACTIVE. 9362306a36Sopenharmony_ci */ 9462306a36Sopenharmony_ciint qib_count_active_units(void) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci struct qib_devdata *dd; 9762306a36Sopenharmony_ci struct qib_pportdata *ppd; 9862306a36Sopenharmony_ci unsigned long index, flags; 9962306a36Sopenharmony_ci int pidx, nunits_active = 0; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci xa_lock_irqsave(&qib_dev_table, flags); 10262306a36Sopenharmony_ci xa_for_each(&qib_dev_table, index, dd) { 10362306a36Sopenharmony_ci if (!(dd->flags & QIB_PRESENT) || !dd->kregbase) 10462306a36Sopenharmony_ci continue; 10562306a36Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 10662306a36Sopenharmony_ci ppd = dd->pport + pidx; 10762306a36Sopenharmony_ci if (ppd->lid && (ppd->lflags & (QIBL_LINKINIT | 10862306a36Sopenharmony_ci QIBL_LINKARMED | QIBL_LINKACTIVE))) { 10962306a36Sopenharmony_ci nunits_active++; 11062306a36Sopenharmony_ci break; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci xa_unlock_irqrestore(&qib_dev_table, flags); 11562306a36Sopenharmony_ci return nunits_active; 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci/* 11962306a36Sopenharmony_ci * Return count of all units, optionally return in arguments 12062306a36Sopenharmony_ci * the number of usable (present) units, and the number of 12162306a36Sopenharmony_ci * ports that are up. 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_ciint qib_count_units(int *npresentp, int *nupp) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci int nunits = 0, npresent = 0, nup = 0; 12662306a36Sopenharmony_ci struct qib_devdata *dd; 12762306a36Sopenharmony_ci unsigned long index, flags; 12862306a36Sopenharmony_ci int pidx; 12962306a36Sopenharmony_ci struct qib_pportdata *ppd; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci xa_lock_irqsave(&qib_dev_table, flags); 13262306a36Sopenharmony_ci xa_for_each(&qib_dev_table, index, dd) { 13362306a36Sopenharmony_ci nunits++; 13462306a36Sopenharmony_ci if ((dd->flags & QIB_PRESENT) && dd->kregbase) 13562306a36Sopenharmony_ci npresent++; 13662306a36Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 13762306a36Sopenharmony_ci ppd = dd->pport + pidx; 13862306a36Sopenharmony_ci if (ppd->lid && (ppd->lflags & (QIBL_LINKINIT | 13962306a36Sopenharmony_ci QIBL_LINKARMED | QIBL_LINKACTIVE))) 14062306a36Sopenharmony_ci nup++; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci xa_unlock_irqrestore(&qib_dev_table, flags); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci if (npresentp) 14662306a36Sopenharmony_ci *npresentp = npresent; 14762306a36Sopenharmony_ci if (nupp) 14862306a36Sopenharmony_ci *nupp = nup; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci return nunits; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/** 15462306a36Sopenharmony_ci * qib_wait_linkstate - wait for an IB link state change to occur 15562306a36Sopenharmony_ci * @ppd: the qlogic_ib device 15662306a36Sopenharmony_ci * @state: the state to wait for 15762306a36Sopenharmony_ci * @msecs: the number of milliseconds to wait 15862306a36Sopenharmony_ci * 15962306a36Sopenharmony_ci * wait up to msecs milliseconds for IB link state change to occur for 16062306a36Sopenharmony_ci * now, take the easy polling route. Currently used only by 16162306a36Sopenharmony_ci * qib_set_linkstate. Returns 0 if state reached, otherwise 16262306a36Sopenharmony_ci * -ETIMEDOUT state can have multiple states set, for any of several 16362306a36Sopenharmony_ci * transitions. 16462306a36Sopenharmony_ci */ 16562306a36Sopenharmony_ciint qib_wait_linkstate(struct qib_pportdata *ppd, u32 state, int msecs) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci int ret; 16862306a36Sopenharmony_ci unsigned long flags; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci spin_lock_irqsave(&ppd->lflags_lock, flags); 17162306a36Sopenharmony_ci if (ppd->state_wanted) { 17262306a36Sopenharmony_ci spin_unlock_irqrestore(&ppd->lflags_lock, flags); 17362306a36Sopenharmony_ci ret = -EBUSY; 17462306a36Sopenharmony_ci goto bail; 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci ppd->state_wanted = state; 17762306a36Sopenharmony_ci spin_unlock_irqrestore(&ppd->lflags_lock, flags); 17862306a36Sopenharmony_ci wait_event_interruptible_timeout(ppd->state_wait, 17962306a36Sopenharmony_ci (ppd->lflags & state), 18062306a36Sopenharmony_ci msecs_to_jiffies(msecs)); 18162306a36Sopenharmony_ci spin_lock_irqsave(&ppd->lflags_lock, flags); 18262306a36Sopenharmony_ci ppd->state_wanted = 0; 18362306a36Sopenharmony_ci spin_unlock_irqrestore(&ppd->lflags_lock, flags); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci if (!(ppd->lflags & state)) 18662306a36Sopenharmony_ci ret = -ETIMEDOUT; 18762306a36Sopenharmony_ci else 18862306a36Sopenharmony_ci ret = 0; 18962306a36Sopenharmony_cibail: 19062306a36Sopenharmony_ci return ret; 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ciint qib_set_linkstate(struct qib_pportdata *ppd, u8 newstate) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci u32 lstate; 19662306a36Sopenharmony_ci int ret; 19762306a36Sopenharmony_ci struct qib_devdata *dd = ppd->dd; 19862306a36Sopenharmony_ci unsigned long flags; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci switch (newstate) { 20162306a36Sopenharmony_ci case QIB_IB_LINKDOWN_ONLY: 20262306a36Sopenharmony_ci dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE, 20362306a36Sopenharmony_ci IB_LINKCMD_DOWN | IB_LINKINITCMD_NOP); 20462306a36Sopenharmony_ci /* don't wait */ 20562306a36Sopenharmony_ci ret = 0; 20662306a36Sopenharmony_ci goto bail; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci case QIB_IB_LINKDOWN: 20962306a36Sopenharmony_ci dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE, 21062306a36Sopenharmony_ci IB_LINKCMD_DOWN | IB_LINKINITCMD_POLL); 21162306a36Sopenharmony_ci /* don't wait */ 21262306a36Sopenharmony_ci ret = 0; 21362306a36Sopenharmony_ci goto bail; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci case QIB_IB_LINKDOWN_SLEEP: 21662306a36Sopenharmony_ci dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE, 21762306a36Sopenharmony_ci IB_LINKCMD_DOWN | IB_LINKINITCMD_SLEEP); 21862306a36Sopenharmony_ci /* don't wait */ 21962306a36Sopenharmony_ci ret = 0; 22062306a36Sopenharmony_ci goto bail; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci case QIB_IB_LINKDOWN_DISABLE: 22362306a36Sopenharmony_ci dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE, 22462306a36Sopenharmony_ci IB_LINKCMD_DOWN | IB_LINKINITCMD_DISABLE); 22562306a36Sopenharmony_ci /* don't wait */ 22662306a36Sopenharmony_ci ret = 0; 22762306a36Sopenharmony_ci goto bail; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci case QIB_IB_LINKARM: 23062306a36Sopenharmony_ci if (ppd->lflags & QIBL_LINKARMED) { 23162306a36Sopenharmony_ci ret = 0; 23262306a36Sopenharmony_ci goto bail; 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci if (!(ppd->lflags & (QIBL_LINKINIT | QIBL_LINKACTIVE))) { 23562306a36Sopenharmony_ci ret = -EINVAL; 23662306a36Sopenharmony_ci goto bail; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci /* 23962306a36Sopenharmony_ci * Since the port can be ACTIVE when we ask for ARMED, 24062306a36Sopenharmony_ci * clear QIBL_LINKV so we can wait for a transition. 24162306a36Sopenharmony_ci * If the link isn't ARMED, then something else happened 24262306a36Sopenharmony_ci * and there is no point waiting for ARMED. 24362306a36Sopenharmony_ci */ 24462306a36Sopenharmony_ci spin_lock_irqsave(&ppd->lflags_lock, flags); 24562306a36Sopenharmony_ci ppd->lflags &= ~QIBL_LINKV; 24662306a36Sopenharmony_ci spin_unlock_irqrestore(&ppd->lflags_lock, flags); 24762306a36Sopenharmony_ci dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE, 24862306a36Sopenharmony_ci IB_LINKCMD_ARMED | IB_LINKINITCMD_NOP); 24962306a36Sopenharmony_ci lstate = QIBL_LINKV; 25062306a36Sopenharmony_ci break; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci case QIB_IB_LINKACTIVE: 25362306a36Sopenharmony_ci if (ppd->lflags & QIBL_LINKACTIVE) { 25462306a36Sopenharmony_ci ret = 0; 25562306a36Sopenharmony_ci goto bail; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci if (!(ppd->lflags & QIBL_LINKARMED)) { 25862306a36Sopenharmony_ci ret = -EINVAL; 25962306a36Sopenharmony_ci goto bail; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE, 26262306a36Sopenharmony_ci IB_LINKCMD_ACTIVE | IB_LINKINITCMD_NOP); 26362306a36Sopenharmony_ci lstate = QIBL_LINKACTIVE; 26462306a36Sopenharmony_ci break; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci default: 26762306a36Sopenharmony_ci ret = -EINVAL; 26862306a36Sopenharmony_ci goto bail; 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci ret = qib_wait_linkstate(ppd, lstate, 10); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cibail: 27362306a36Sopenharmony_ci return ret; 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci/* 27762306a36Sopenharmony_ci * Get address of eager buffer from it's index (allocated in chunks, not 27862306a36Sopenharmony_ci * contiguous). 27962306a36Sopenharmony_ci */ 28062306a36Sopenharmony_cistatic inline void *qib_get_egrbuf(const struct qib_ctxtdata *rcd, u32 etail) 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci const u32 chunk = etail >> rcd->rcvegrbufs_perchunk_shift; 28362306a36Sopenharmony_ci const u32 idx = etail & ((u32)rcd->rcvegrbufs_perchunk - 1); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci return rcd->rcvegrbuf[chunk] + (idx << rcd->dd->rcvegrbufsize_shift); 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci/* 28962306a36Sopenharmony_ci * Returns 1 if error was a CRC, else 0. 29062306a36Sopenharmony_ci * Needed for some chip's synthesized error counters. 29162306a36Sopenharmony_ci */ 29262306a36Sopenharmony_cistatic u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd, 29362306a36Sopenharmony_ci u32 ctxt, u32 eflags, u32 l, u32 etail, 29462306a36Sopenharmony_ci __le32 *rhf_addr, struct qib_message_header *rhdr) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci u32 ret = 0; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci if (eflags & (QLOGIC_IB_RHF_H_ICRCERR | QLOGIC_IB_RHF_H_VCRCERR)) 29962306a36Sopenharmony_ci ret = 1; 30062306a36Sopenharmony_ci else if (eflags == QLOGIC_IB_RHF_H_TIDERR) { 30162306a36Sopenharmony_ci /* For TIDERR and RC QPs premptively schedule a NAK */ 30262306a36Sopenharmony_ci struct ib_header *hdr = (struct ib_header *)rhdr; 30362306a36Sopenharmony_ci struct ib_other_headers *ohdr = NULL; 30462306a36Sopenharmony_ci struct qib_ibport *ibp = &ppd->ibport_data; 30562306a36Sopenharmony_ci struct qib_devdata *dd = ppd->dd; 30662306a36Sopenharmony_ci struct rvt_dev_info *rdi = &dd->verbs_dev.rdi; 30762306a36Sopenharmony_ci struct rvt_qp *qp = NULL; 30862306a36Sopenharmony_ci u32 tlen = qib_hdrget_length_in_bytes(rhf_addr); 30962306a36Sopenharmony_ci u16 lid = be16_to_cpu(hdr->lrh[1]); 31062306a36Sopenharmony_ci int lnh = be16_to_cpu(hdr->lrh[0]) & 3; 31162306a36Sopenharmony_ci u32 qp_num; 31262306a36Sopenharmony_ci u32 opcode; 31362306a36Sopenharmony_ci u32 psn; 31462306a36Sopenharmony_ci int diff; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* Sanity check packet */ 31762306a36Sopenharmony_ci if (tlen < 24) 31862306a36Sopenharmony_ci goto drop; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci if (lid < be16_to_cpu(IB_MULTICAST_LID_BASE)) { 32162306a36Sopenharmony_ci lid &= ~((1 << ppd->lmc) - 1); 32262306a36Sopenharmony_ci if (unlikely(lid != ppd->lid)) 32362306a36Sopenharmony_ci goto drop; 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci /* Check for GRH */ 32762306a36Sopenharmony_ci if (lnh == QIB_LRH_BTH) 32862306a36Sopenharmony_ci ohdr = &hdr->u.oth; 32962306a36Sopenharmony_ci else if (lnh == QIB_LRH_GRH) { 33062306a36Sopenharmony_ci u32 vtf; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci ohdr = &hdr->u.l.oth; 33362306a36Sopenharmony_ci if (hdr->u.l.grh.next_hdr != IB_GRH_NEXT_HDR) 33462306a36Sopenharmony_ci goto drop; 33562306a36Sopenharmony_ci vtf = be32_to_cpu(hdr->u.l.grh.version_tclass_flow); 33662306a36Sopenharmony_ci if ((vtf >> IB_GRH_VERSION_SHIFT) != IB_GRH_VERSION) 33762306a36Sopenharmony_ci goto drop; 33862306a36Sopenharmony_ci } else 33962306a36Sopenharmony_ci goto drop; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci /* Get opcode and PSN from packet */ 34262306a36Sopenharmony_ci opcode = be32_to_cpu(ohdr->bth[0]); 34362306a36Sopenharmony_ci opcode >>= 24; 34462306a36Sopenharmony_ci psn = be32_to_cpu(ohdr->bth[2]); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci /* Get the destination QP number. */ 34762306a36Sopenharmony_ci qp_num = be32_to_cpu(ohdr->bth[1]) & RVT_QPN_MASK; 34862306a36Sopenharmony_ci if (qp_num != QIB_MULTICAST_QPN) { 34962306a36Sopenharmony_ci int ruc_res; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci rcu_read_lock(); 35262306a36Sopenharmony_ci qp = rvt_lookup_qpn(rdi, &ibp->rvp, qp_num); 35362306a36Sopenharmony_ci if (!qp) { 35462306a36Sopenharmony_ci rcu_read_unlock(); 35562306a36Sopenharmony_ci goto drop; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci /* 35962306a36Sopenharmony_ci * Handle only RC QPs - for other QP types drop error 36062306a36Sopenharmony_ci * packet. 36162306a36Sopenharmony_ci */ 36262306a36Sopenharmony_ci spin_lock(&qp->r_lock); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci /* Check for valid receive state. */ 36562306a36Sopenharmony_ci if (!(ib_rvt_state_ops[qp->state] & 36662306a36Sopenharmony_ci RVT_PROCESS_RECV_OK)) { 36762306a36Sopenharmony_ci ibp->rvp.n_pkt_drops++; 36862306a36Sopenharmony_ci goto unlock; 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci switch (qp->ibqp.qp_type) { 37262306a36Sopenharmony_ci case IB_QPT_RC: 37362306a36Sopenharmony_ci ruc_res = 37462306a36Sopenharmony_ci qib_ruc_check_hdr( 37562306a36Sopenharmony_ci ibp, hdr, 37662306a36Sopenharmony_ci lnh == QIB_LRH_GRH, 37762306a36Sopenharmony_ci qp, 37862306a36Sopenharmony_ci be32_to_cpu(ohdr->bth[0])); 37962306a36Sopenharmony_ci if (ruc_res) 38062306a36Sopenharmony_ci goto unlock; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* Only deal with RDMA Writes for now */ 38362306a36Sopenharmony_ci if (opcode < 38462306a36Sopenharmony_ci IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST) { 38562306a36Sopenharmony_ci diff = qib_cmp24(psn, qp->r_psn); 38662306a36Sopenharmony_ci if (!qp->r_nak_state && diff >= 0) { 38762306a36Sopenharmony_ci ibp->rvp.n_rc_seqnak++; 38862306a36Sopenharmony_ci qp->r_nak_state = 38962306a36Sopenharmony_ci IB_NAK_PSN_ERROR; 39062306a36Sopenharmony_ci /* Use the expected PSN. */ 39162306a36Sopenharmony_ci qp->r_ack_psn = qp->r_psn; 39262306a36Sopenharmony_ci /* 39362306a36Sopenharmony_ci * Wait to send the sequence 39462306a36Sopenharmony_ci * NAK until all packets 39562306a36Sopenharmony_ci * in the receive queue have 39662306a36Sopenharmony_ci * been processed. 39762306a36Sopenharmony_ci * Otherwise, we end up 39862306a36Sopenharmony_ci * propagating congestion. 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_ci if (list_empty(&qp->rspwait)) { 40162306a36Sopenharmony_ci qp->r_flags |= 40262306a36Sopenharmony_ci RVT_R_RSP_NAK; 40362306a36Sopenharmony_ci rvt_get_qp(qp); 40462306a36Sopenharmony_ci list_add_tail( 40562306a36Sopenharmony_ci &qp->rspwait, 40662306a36Sopenharmony_ci &rcd->qp_wait_list); 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci } /* Out of sequence NAK */ 40962306a36Sopenharmony_ci } /* QP Request NAKs */ 41062306a36Sopenharmony_ci break; 41162306a36Sopenharmony_ci case IB_QPT_SMI: 41262306a36Sopenharmony_ci case IB_QPT_GSI: 41362306a36Sopenharmony_ci case IB_QPT_UD: 41462306a36Sopenharmony_ci case IB_QPT_UC: 41562306a36Sopenharmony_ci default: 41662306a36Sopenharmony_ci /* For now don't handle any other QP types */ 41762306a36Sopenharmony_ci break; 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ciunlock: 42162306a36Sopenharmony_ci spin_unlock(&qp->r_lock); 42262306a36Sopenharmony_ci rcu_read_unlock(); 42362306a36Sopenharmony_ci } /* Unicast QP */ 42462306a36Sopenharmony_ci } /* Valid packet with TIDErr */ 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cidrop: 42762306a36Sopenharmony_ci return ret; 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci/* 43162306a36Sopenharmony_ci * qib_kreceive - receive a packet 43262306a36Sopenharmony_ci * @rcd: the qlogic_ib context 43362306a36Sopenharmony_ci * @llic: gets count of good packets needed to clear lli, 43462306a36Sopenharmony_ci * (used with chips that need need to track crcs for lli) 43562306a36Sopenharmony_ci * 43662306a36Sopenharmony_ci * called from interrupt handler for errors or receive interrupt 43762306a36Sopenharmony_ci * Returns number of CRC error packets, needed by some chips for 43862306a36Sopenharmony_ci * local link integrity tracking. crcs are adjusted down by following 43962306a36Sopenharmony_ci * good packets, if any, and count of good packets is also tracked. 44062306a36Sopenharmony_ci */ 44162306a36Sopenharmony_ciu32 qib_kreceive(struct qib_ctxtdata *rcd, u32 *llic, u32 *npkts) 44262306a36Sopenharmony_ci{ 44362306a36Sopenharmony_ci struct qib_devdata *dd = rcd->dd; 44462306a36Sopenharmony_ci struct qib_pportdata *ppd = rcd->ppd; 44562306a36Sopenharmony_ci __le32 *rhf_addr; 44662306a36Sopenharmony_ci void *ebuf; 44762306a36Sopenharmony_ci const u32 rsize = dd->rcvhdrentsize; /* words */ 44862306a36Sopenharmony_ci const u32 maxcnt = dd->rcvhdrcnt * rsize; /* words */ 44962306a36Sopenharmony_ci u32 etail = -1, l, hdrqtail; 45062306a36Sopenharmony_ci struct qib_message_header *hdr; 45162306a36Sopenharmony_ci u32 eflags, etype, tlen, i = 0, updegr = 0, crcs = 0; 45262306a36Sopenharmony_ci int last; 45362306a36Sopenharmony_ci u64 lval; 45462306a36Sopenharmony_ci struct rvt_qp *qp, *nqp; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci l = rcd->head; 45762306a36Sopenharmony_ci rhf_addr = (__le32 *) rcd->rcvhdrq + l + dd->rhf_offset; 45862306a36Sopenharmony_ci if (dd->flags & QIB_NODMA_RTAIL) { 45962306a36Sopenharmony_ci u32 seq = qib_hdrget_seq(rhf_addr); 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci if (seq != rcd->seq_cnt) 46262306a36Sopenharmony_ci goto bail; 46362306a36Sopenharmony_ci hdrqtail = 0; 46462306a36Sopenharmony_ci } else { 46562306a36Sopenharmony_ci hdrqtail = qib_get_rcvhdrtail(rcd); 46662306a36Sopenharmony_ci if (l == hdrqtail) 46762306a36Sopenharmony_ci goto bail; 46862306a36Sopenharmony_ci smp_rmb(); /* prevent speculative reads of dma'ed hdrq */ 46962306a36Sopenharmony_ci } 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci for (last = 0, i = 1; !last; i += !last) { 47262306a36Sopenharmony_ci hdr = dd->f_get_msgheader(dd, rhf_addr); 47362306a36Sopenharmony_ci eflags = qib_hdrget_err_flags(rhf_addr); 47462306a36Sopenharmony_ci etype = qib_hdrget_rcv_type(rhf_addr); 47562306a36Sopenharmony_ci /* total length */ 47662306a36Sopenharmony_ci tlen = qib_hdrget_length_in_bytes(rhf_addr); 47762306a36Sopenharmony_ci ebuf = NULL; 47862306a36Sopenharmony_ci if ((dd->flags & QIB_NODMA_RTAIL) ? 47962306a36Sopenharmony_ci qib_hdrget_use_egr_buf(rhf_addr) : 48062306a36Sopenharmony_ci (etype != RCVHQ_RCV_TYPE_EXPECTED)) { 48162306a36Sopenharmony_ci etail = qib_hdrget_index(rhf_addr); 48262306a36Sopenharmony_ci updegr = 1; 48362306a36Sopenharmony_ci if (tlen > sizeof(*hdr) || 48462306a36Sopenharmony_ci etype >= RCVHQ_RCV_TYPE_NON_KD) { 48562306a36Sopenharmony_ci ebuf = qib_get_egrbuf(rcd, etail); 48662306a36Sopenharmony_ci prefetch_range(ebuf, tlen - sizeof(*hdr)); 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci if (!eflags) { 49062306a36Sopenharmony_ci u16 lrh_len = be16_to_cpu(hdr->lrh[2]) << 2; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci if (lrh_len != tlen) { 49362306a36Sopenharmony_ci qib_stats.sps_lenerrs++; 49462306a36Sopenharmony_ci goto move_along; 49562306a36Sopenharmony_ci } 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci if (etype == RCVHQ_RCV_TYPE_NON_KD && !eflags && 49862306a36Sopenharmony_ci ebuf == NULL && 49962306a36Sopenharmony_ci tlen > (dd->rcvhdrentsize - 2 + 1 - 50062306a36Sopenharmony_ci qib_hdrget_offset(rhf_addr)) << 2) { 50162306a36Sopenharmony_ci goto move_along; 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci /* 50562306a36Sopenharmony_ci * Both tiderr and qibhdrerr are set for all plain IB 50662306a36Sopenharmony_ci * packets; only qibhdrerr should be set. 50762306a36Sopenharmony_ci */ 50862306a36Sopenharmony_ci if (unlikely(eflags)) 50962306a36Sopenharmony_ci crcs += qib_rcv_hdrerr(rcd, ppd, rcd->ctxt, eflags, l, 51062306a36Sopenharmony_ci etail, rhf_addr, hdr); 51162306a36Sopenharmony_ci else if (etype == RCVHQ_RCV_TYPE_NON_KD) { 51262306a36Sopenharmony_ci qib_ib_rcv(rcd, hdr, ebuf, tlen); 51362306a36Sopenharmony_ci if (crcs) 51462306a36Sopenharmony_ci crcs--; 51562306a36Sopenharmony_ci else if (llic && *llic) 51662306a36Sopenharmony_ci --*llic; 51762306a36Sopenharmony_ci } 51862306a36Sopenharmony_cimove_along: 51962306a36Sopenharmony_ci l += rsize; 52062306a36Sopenharmony_ci if (l >= maxcnt) 52162306a36Sopenharmony_ci l = 0; 52262306a36Sopenharmony_ci if (i == QIB_MAX_PKT_RECV) 52362306a36Sopenharmony_ci last = 1; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci rhf_addr = (__le32 *) rcd->rcvhdrq + l + dd->rhf_offset; 52662306a36Sopenharmony_ci if (dd->flags & QIB_NODMA_RTAIL) { 52762306a36Sopenharmony_ci u32 seq = qib_hdrget_seq(rhf_addr); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci if (++rcd->seq_cnt > 13) 53062306a36Sopenharmony_ci rcd->seq_cnt = 1; 53162306a36Sopenharmony_ci if (seq != rcd->seq_cnt) 53262306a36Sopenharmony_ci last = 1; 53362306a36Sopenharmony_ci } else if (l == hdrqtail) 53462306a36Sopenharmony_ci last = 1; 53562306a36Sopenharmony_ci /* 53662306a36Sopenharmony_ci * Update head regs etc., every 16 packets, if not last pkt, 53762306a36Sopenharmony_ci * to help prevent rcvhdrq overflows, when many packets 53862306a36Sopenharmony_ci * are processed and queue is nearly full. 53962306a36Sopenharmony_ci * Don't request an interrupt for intermediate updates. 54062306a36Sopenharmony_ci */ 54162306a36Sopenharmony_ci lval = l; 54262306a36Sopenharmony_ci if (!last && !(i & 0xf)) { 54362306a36Sopenharmony_ci dd->f_update_usrhead(rcd, lval, updegr, etail, i); 54462306a36Sopenharmony_ci updegr = 0; 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci } 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci rcd->head = l; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci /* 55162306a36Sopenharmony_ci * Iterate over all QPs waiting to respond. 55262306a36Sopenharmony_ci * The list won't change since the IRQ is only run on one CPU. 55362306a36Sopenharmony_ci */ 55462306a36Sopenharmony_ci list_for_each_entry_safe(qp, nqp, &rcd->qp_wait_list, rspwait) { 55562306a36Sopenharmony_ci list_del_init(&qp->rspwait); 55662306a36Sopenharmony_ci if (qp->r_flags & RVT_R_RSP_NAK) { 55762306a36Sopenharmony_ci qp->r_flags &= ~RVT_R_RSP_NAK; 55862306a36Sopenharmony_ci qib_send_rc_ack(qp); 55962306a36Sopenharmony_ci } 56062306a36Sopenharmony_ci if (qp->r_flags & RVT_R_RSP_SEND) { 56162306a36Sopenharmony_ci unsigned long flags; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci qp->r_flags &= ~RVT_R_RSP_SEND; 56462306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 56562306a36Sopenharmony_ci if (ib_rvt_state_ops[qp->state] & 56662306a36Sopenharmony_ci RVT_PROCESS_OR_FLUSH_SEND) 56762306a36Sopenharmony_ci qib_schedule_send(qp); 56862306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 56962306a36Sopenharmony_ci } 57062306a36Sopenharmony_ci rvt_put_qp(qp); 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_cibail: 57462306a36Sopenharmony_ci /* Report number of packets consumed */ 57562306a36Sopenharmony_ci if (npkts) 57662306a36Sopenharmony_ci *npkts = i; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci /* 57962306a36Sopenharmony_ci * Always write head at end, and setup rcv interrupt, even 58062306a36Sopenharmony_ci * if no packets were processed. 58162306a36Sopenharmony_ci */ 58262306a36Sopenharmony_ci lval = (u64)rcd->head | dd->rhdrhead_intr_off; 58362306a36Sopenharmony_ci dd->f_update_usrhead(rcd, lval, updegr, etail, i); 58462306a36Sopenharmony_ci return crcs; 58562306a36Sopenharmony_ci} 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci/** 58862306a36Sopenharmony_ci * qib_set_mtu - set the MTU 58962306a36Sopenharmony_ci * @ppd: the perport data 59062306a36Sopenharmony_ci * @arg: the new MTU 59162306a36Sopenharmony_ci * 59262306a36Sopenharmony_ci * We can handle "any" incoming size, the issue here is whether we 59362306a36Sopenharmony_ci * need to restrict our outgoing size. For now, we don't do any 59462306a36Sopenharmony_ci * sanity checking on this, and we don't deal with what happens to 59562306a36Sopenharmony_ci * programs that are already running when the size changes. 59662306a36Sopenharmony_ci * NOTE: changing the MTU will usually cause the IBC to go back to 59762306a36Sopenharmony_ci * link INIT state... 59862306a36Sopenharmony_ci */ 59962306a36Sopenharmony_ciint qib_set_mtu(struct qib_pportdata *ppd, u16 arg) 60062306a36Sopenharmony_ci{ 60162306a36Sopenharmony_ci u32 piosize; 60262306a36Sopenharmony_ci int ret, chk; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci if (arg != 256 && arg != 512 && arg != 1024 && arg != 2048 && 60562306a36Sopenharmony_ci arg != 4096) { 60662306a36Sopenharmony_ci ret = -EINVAL; 60762306a36Sopenharmony_ci goto bail; 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci chk = ib_mtu_enum_to_int(qib_ibmtu); 61062306a36Sopenharmony_ci if (chk > 0 && arg > chk) { 61162306a36Sopenharmony_ci ret = -EINVAL; 61262306a36Sopenharmony_ci goto bail; 61362306a36Sopenharmony_ci } 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci piosize = ppd->ibmaxlen; 61662306a36Sopenharmony_ci ppd->ibmtu = arg; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci if (arg >= (piosize - QIB_PIO_MAXIBHDR)) { 61962306a36Sopenharmony_ci /* Only if it's not the initial value (or reset to it) */ 62062306a36Sopenharmony_ci if (piosize != ppd->init_ibmaxlen) { 62162306a36Sopenharmony_ci if (arg > piosize && arg <= ppd->init_ibmaxlen) 62262306a36Sopenharmony_ci piosize = ppd->init_ibmaxlen - 2 * sizeof(u32); 62362306a36Sopenharmony_ci ppd->ibmaxlen = piosize; 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci } else if ((arg + QIB_PIO_MAXIBHDR) != ppd->ibmaxlen) { 62662306a36Sopenharmony_ci piosize = arg + QIB_PIO_MAXIBHDR - 2 * sizeof(u32); 62762306a36Sopenharmony_ci ppd->ibmaxlen = piosize; 62862306a36Sopenharmony_ci } 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci ppd->dd->f_set_ib_cfg(ppd, QIB_IB_CFG_MTU, 0); 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci ret = 0; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_cibail: 63562306a36Sopenharmony_ci return ret; 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ciint qib_set_lid(struct qib_pportdata *ppd, u32 lid, u8 lmc) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci struct qib_devdata *dd = ppd->dd; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci ppd->lid = lid; 64362306a36Sopenharmony_ci ppd->lmc = lmc; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci dd->f_set_ib_cfg(ppd, QIB_IB_CFG_LIDLMC, 64662306a36Sopenharmony_ci lid | (~((1U << lmc) - 1)) << 16); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci qib_devinfo(dd->pcidev, "IB%u:%u got a lid: 0x%x\n", 64962306a36Sopenharmony_ci dd->unit, ppd->port, lid); 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci return 0; 65262306a36Sopenharmony_ci} 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci/* 65562306a36Sopenharmony_ci * Following deal with the "obviously simple" task of overriding the state 65662306a36Sopenharmony_ci * of the LEDS, which normally indicate link physical and logical status. 65762306a36Sopenharmony_ci * The complications arise in dealing with different hardware mappings 65862306a36Sopenharmony_ci * and the board-dependent routine being called from interrupts. 65962306a36Sopenharmony_ci * and then there's the requirement to _flash_ them. 66062306a36Sopenharmony_ci */ 66162306a36Sopenharmony_ci#define LED_OVER_FREQ_SHIFT 8 66262306a36Sopenharmony_ci#define LED_OVER_FREQ_MASK (0xFF<<LED_OVER_FREQ_SHIFT) 66362306a36Sopenharmony_ci/* Below is "non-zero" to force override, but both actual LEDs are off */ 66462306a36Sopenharmony_ci#define LED_OVER_BOTH_OFF (8) 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_cistatic void qib_run_led_override(struct timer_list *t) 66762306a36Sopenharmony_ci{ 66862306a36Sopenharmony_ci struct qib_pportdata *ppd = from_timer(ppd, t, 66962306a36Sopenharmony_ci led_override_timer); 67062306a36Sopenharmony_ci struct qib_devdata *dd = ppd->dd; 67162306a36Sopenharmony_ci int timeoff; 67262306a36Sopenharmony_ci int ph_idx; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci if (!(dd->flags & QIB_INITTED)) 67562306a36Sopenharmony_ci return; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci ph_idx = ppd->led_override_phase++ & 1; 67862306a36Sopenharmony_ci ppd->led_override = ppd->led_override_vals[ph_idx]; 67962306a36Sopenharmony_ci timeoff = ppd->led_override_timeoff; 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci dd->f_setextled(ppd, 1); 68262306a36Sopenharmony_ci /* 68362306a36Sopenharmony_ci * don't re-fire the timer if user asked for it to be off; we let 68462306a36Sopenharmony_ci * it fire one more time after they turn it off to simplify 68562306a36Sopenharmony_ci */ 68662306a36Sopenharmony_ci if (ppd->led_override_vals[0] || ppd->led_override_vals[1]) 68762306a36Sopenharmony_ci mod_timer(&ppd->led_override_timer, jiffies + timeoff); 68862306a36Sopenharmony_ci} 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_civoid qib_set_led_override(struct qib_pportdata *ppd, unsigned int val) 69162306a36Sopenharmony_ci{ 69262306a36Sopenharmony_ci struct qib_devdata *dd = ppd->dd; 69362306a36Sopenharmony_ci int timeoff, freq; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci if (!(dd->flags & QIB_INITTED)) 69662306a36Sopenharmony_ci return; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci /* First check if we are blinking. If not, use 1HZ polling */ 69962306a36Sopenharmony_ci timeoff = HZ; 70062306a36Sopenharmony_ci freq = (val & LED_OVER_FREQ_MASK) >> LED_OVER_FREQ_SHIFT; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci if (freq) { 70362306a36Sopenharmony_ci /* For blink, set each phase from one nybble of val */ 70462306a36Sopenharmony_ci ppd->led_override_vals[0] = val & 0xF; 70562306a36Sopenharmony_ci ppd->led_override_vals[1] = (val >> 4) & 0xF; 70662306a36Sopenharmony_ci timeoff = (HZ << 4)/freq; 70762306a36Sopenharmony_ci } else { 70862306a36Sopenharmony_ci /* Non-blink set both phases the same. */ 70962306a36Sopenharmony_ci ppd->led_override_vals[0] = val & 0xF; 71062306a36Sopenharmony_ci ppd->led_override_vals[1] = val & 0xF; 71162306a36Sopenharmony_ci } 71262306a36Sopenharmony_ci ppd->led_override_timeoff = timeoff; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci /* 71562306a36Sopenharmony_ci * If the timer has not already been started, do so. Use a "quick" 71662306a36Sopenharmony_ci * timeout so the function will be called soon, to look at our request. 71762306a36Sopenharmony_ci */ 71862306a36Sopenharmony_ci if (atomic_inc_return(&ppd->led_override_timer_active) == 1) { 71962306a36Sopenharmony_ci /* Need to start timer */ 72062306a36Sopenharmony_ci timer_setup(&ppd->led_override_timer, qib_run_led_override, 0); 72162306a36Sopenharmony_ci ppd->led_override_timer.expires = jiffies + 1; 72262306a36Sopenharmony_ci add_timer(&ppd->led_override_timer); 72362306a36Sopenharmony_ci } else { 72462306a36Sopenharmony_ci if (ppd->led_override_vals[0] || ppd->led_override_vals[1]) 72562306a36Sopenharmony_ci mod_timer(&ppd->led_override_timer, jiffies + 1); 72662306a36Sopenharmony_ci atomic_dec(&ppd->led_override_timer_active); 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci} 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci/** 73162306a36Sopenharmony_ci * qib_reset_device - reset the chip if possible 73262306a36Sopenharmony_ci * @unit: the device to reset 73362306a36Sopenharmony_ci * 73462306a36Sopenharmony_ci * Whether or not reset is successful, we attempt to re-initialize the chip 73562306a36Sopenharmony_ci * (that is, much like a driver unload/reload). We clear the INITTED flag 73662306a36Sopenharmony_ci * so that the various entry points will fail until we reinitialize. For 73762306a36Sopenharmony_ci * now, we only allow this if no user contexts are open that use chip resources 73862306a36Sopenharmony_ci */ 73962306a36Sopenharmony_ciint qib_reset_device(int unit) 74062306a36Sopenharmony_ci{ 74162306a36Sopenharmony_ci int ret, i; 74262306a36Sopenharmony_ci struct qib_devdata *dd = qib_lookup(unit); 74362306a36Sopenharmony_ci struct qib_pportdata *ppd; 74462306a36Sopenharmony_ci unsigned long flags; 74562306a36Sopenharmony_ci int pidx; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci if (!dd) { 74862306a36Sopenharmony_ci ret = -ENODEV; 74962306a36Sopenharmony_ci goto bail; 75062306a36Sopenharmony_ci } 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci qib_devinfo(dd->pcidev, "Reset on unit %u requested\n", unit); 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci if (!dd->kregbase || !(dd->flags & QIB_PRESENT)) { 75562306a36Sopenharmony_ci qib_devinfo(dd->pcidev, 75662306a36Sopenharmony_ci "Invalid unit number %u or not initialized or not present\n", 75762306a36Sopenharmony_ci unit); 75862306a36Sopenharmony_ci ret = -ENXIO; 75962306a36Sopenharmony_ci goto bail; 76062306a36Sopenharmony_ci } 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci spin_lock_irqsave(&dd->uctxt_lock, flags); 76362306a36Sopenharmony_ci if (dd->rcd) 76462306a36Sopenharmony_ci for (i = dd->first_user_ctxt; i < dd->cfgctxts; i++) { 76562306a36Sopenharmony_ci if (!dd->rcd[i] || !dd->rcd[i]->cnt) 76662306a36Sopenharmony_ci continue; 76762306a36Sopenharmony_ci spin_unlock_irqrestore(&dd->uctxt_lock, flags); 76862306a36Sopenharmony_ci ret = -EBUSY; 76962306a36Sopenharmony_ci goto bail; 77062306a36Sopenharmony_ci } 77162306a36Sopenharmony_ci spin_unlock_irqrestore(&dd->uctxt_lock, flags); 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 77462306a36Sopenharmony_ci ppd = dd->pport + pidx; 77562306a36Sopenharmony_ci if (atomic_read(&ppd->led_override_timer_active)) { 77662306a36Sopenharmony_ci /* Need to stop LED timer, _then_ shut off LEDs */ 77762306a36Sopenharmony_ci del_timer_sync(&ppd->led_override_timer); 77862306a36Sopenharmony_ci atomic_set(&ppd->led_override_timer_active, 0); 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci /* Shut off LEDs after we are sure timer is not running */ 78262306a36Sopenharmony_ci ppd->led_override = LED_OVER_BOTH_OFF; 78362306a36Sopenharmony_ci dd->f_setextled(ppd, 0); 78462306a36Sopenharmony_ci if (dd->flags & QIB_HAS_SEND_DMA) 78562306a36Sopenharmony_ci qib_teardown_sdma(ppd); 78662306a36Sopenharmony_ci } 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci ret = dd->f_reset(dd); 78962306a36Sopenharmony_ci if (ret == 1) 79062306a36Sopenharmony_ci ret = qib_init(dd, 1); 79162306a36Sopenharmony_ci else 79262306a36Sopenharmony_ci ret = -EAGAIN; 79362306a36Sopenharmony_ci if (ret) 79462306a36Sopenharmony_ci qib_dev_err(dd, 79562306a36Sopenharmony_ci "Reinitialize unit %u after reset failed with %d\n", 79662306a36Sopenharmony_ci unit, ret); 79762306a36Sopenharmony_ci else 79862306a36Sopenharmony_ci qib_devinfo(dd->pcidev, 79962306a36Sopenharmony_ci "Reinitialized unit %u after resetting\n", 80062306a36Sopenharmony_ci unit); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_cibail: 80362306a36Sopenharmony_ci return ret; 80462306a36Sopenharmony_ci} 805