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