18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2012, 2013 Intel Corporation. All rights reserved. 38c2ecf20Sopenharmony_ci * Copyright (c) 2006 - 2012 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/pci.h> 368c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 378c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 388c2ecf20Sopenharmony_ci#include <linux/delay.h> 398c2ecf20Sopenharmony_ci#include <linux/module.h> 408c2ecf20Sopenharmony_ci#include <linux/printk.h> 418c2ecf20Sopenharmony_ci#ifdef CONFIG_INFINIBAND_QIB_DCA 428c2ecf20Sopenharmony_ci#include <linux/dca.h> 438c2ecf20Sopenharmony_ci#endif 448c2ecf20Sopenharmony_ci#include <rdma/rdma_vt.h> 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#include "qib.h" 478c2ecf20Sopenharmony_ci#include "qib_common.h" 488c2ecf20Sopenharmony_ci#include "qib_mad.h" 498c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 508c2ecf20Sopenharmony_ci#include "qib_debugfs.h" 518c2ecf20Sopenharmony_ci#include "qib_verbs.h" 528c2ecf20Sopenharmony_ci#endif 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#undef pr_fmt 558c2ecf20Sopenharmony_ci#define pr_fmt(fmt) QIB_DRV_NAME ": " fmt 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* 588c2ecf20Sopenharmony_ci * min buffers we want to have per context, after driver 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_ci#define QIB_MIN_USER_CTXT_BUFCNT 7 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#define QLOGIC_IB_R_SOFTWARE_MASK 0xFF 638c2ecf20Sopenharmony_ci#define QLOGIC_IB_R_SOFTWARE_SHIFT 24 648c2ecf20Sopenharmony_ci#define QLOGIC_IB_R_EMULATOR_MASK (1ULL<<62) 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/* 678c2ecf20Sopenharmony_ci * Number of ctxts we are configured to use (to allow for more pio 688c2ecf20Sopenharmony_ci * buffers per ctxt, etc.) Zero means use chip value. 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_ciushort qib_cfgctxts; 718c2ecf20Sopenharmony_cimodule_param_named(cfgctxts, qib_cfgctxts, ushort, S_IRUGO); 728c2ecf20Sopenharmony_ciMODULE_PARM_DESC(cfgctxts, "Set max number of contexts to use"); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ciunsigned qib_numa_aware; 758c2ecf20Sopenharmony_cimodule_param_named(numa_aware, qib_numa_aware, uint, S_IRUGO); 768c2ecf20Sopenharmony_ciMODULE_PARM_DESC(numa_aware, 778c2ecf20Sopenharmony_ci "0 -> PSM allocation close to HCA, 1 -> PSM allocation local to process"); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* 808c2ecf20Sopenharmony_ci * If set, do not write to any regs if avoidable, hack to allow 818c2ecf20Sopenharmony_ci * check for deranged default register values. 828c2ecf20Sopenharmony_ci */ 838c2ecf20Sopenharmony_ciushort qib_mini_init; 848c2ecf20Sopenharmony_cimodule_param_named(mini_init, qib_mini_init, ushort, S_IRUGO); 858c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mini_init, "If set, do minimal diag init"); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ciunsigned qib_n_krcv_queues; 888c2ecf20Sopenharmony_cimodule_param_named(krcvqs, qib_n_krcv_queues, uint, S_IRUGO); 898c2ecf20Sopenharmony_ciMODULE_PARM_DESC(krcvqs, "number of kernel receive queues per IB port"); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ciunsigned qib_cc_table_size; 928c2ecf20Sopenharmony_cimodule_param_named(cc_table_size, qib_cc_table_size, uint, S_IRUGO); 938c2ecf20Sopenharmony_ciMODULE_PARM_DESC(cc_table_size, "Congestion control table entries 0 (CCA disabled - default), min = 128, max = 1984"); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic void verify_interrupt(struct timer_list *); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ciDEFINE_XARRAY_FLAGS(qib_dev_table, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ); 988c2ecf20Sopenharmony_ciu32 qib_cpulist_count; 998c2ecf20Sopenharmony_ciunsigned long *qib_cpulist; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* set number of contexts we'll actually use */ 1028c2ecf20Sopenharmony_civoid qib_set_ctxtcnt(struct qib_devdata *dd) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci if (!qib_cfgctxts) { 1058c2ecf20Sopenharmony_ci dd->cfgctxts = dd->first_user_ctxt + num_online_cpus(); 1068c2ecf20Sopenharmony_ci if (dd->cfgctxts > dd->ctxtcnt) 1078c2ecf20Sopenharmony_ci dd->cfgctxts = dd->ctxtcnt; 1088c2ecf20Sopenharmony_ci } else if (qib_cfgctxts < dd->num_pports) 1098c2ecf20Sopenharmony_ci dd->cfgctxts = dd->ctxtcnt; 1108c2ecf20Sopenharmony_ci else if (qib_cfgctxts <= dd->ctxtcnt) 1118c2ecf20Sopenharmony_ci dd->cfgctxts = qib_cfgctxts; 1128c2ecf20Sopenharmony_ci else 1138c2ecf20Sopenharmony_ci dd->cfgctxts = dd->ctxtcnt; 1148c2ecf20Sopenharmony_ci dd->freectxts = (dd->first_user_ctxt > dd->cfgctxts) ? 0 : 1158c2ecf20Sopenharmony_ci dd->cfgctxts - dd->first_user_ctxt; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/* 1198c2ecf20Sopenharmony_ci * Common code for creating the receive context array. 1208c2ecf20Sopenharmony_ci */ 1218c2ecf20Sopenharmony_ciint qib_create_ctxts(struct qib_devdata *dd) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci unsigned i; 1248c2ecf20Sopenharmony_ci int local_node_id = pcibus_to_node(dd->pcidev->bus); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci if (local_node_id < 0) 1278c2ecf20Sopenharmony_ci local_node_id = numa_node_id(); 1288c2ecf20Sopenharmony_ci dd->assigned_node_id = local_node_id; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* 1318c2ecf20Sopenharmony_ci * Allocate full ctxtcnt array, rather than just cfgctxts, because 1328c2ecf20Sopenharmony_ci * cleanup iterates across all possible ctxts. 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_ci dd->rcd = kcalloc(dd->ctxtcnt, sizeof(*dd->rcd), GFP_KERNEL); 1358c2ecf20Sopenharmony_ci if (!dd->rcd) 1368c2ecf20Sopenharmony_ci return -ENOMEM; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci /* create (one or more) kctxt */ 1398c2ecf20Sopenharmony_ci for (i = 0; i < dd->first_user_ctxt; ++i) { 1408c2ecf20Sopenharmony_ci struct qib_pportdata *ppd; 1418c2ecf20Sopenharmony_ci struct qib_ctxtdata *rcd; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci if (dd->skip_kctxt_mask & (1 << i)) 1448c2ecf20Sopenharmony_ci continue; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci ppd = dd->pport + (i % dd->num_pports); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci rcd = qib_create_ctxtdata(ppd, i, dd->assigned_node_id); 1498c2ecf20Sopenharmony_ci if (!rcd) { 1508c2ecf20Sopenharmony_ci qib_dev_err(dd, 1518c2ecf20Sopenharmony_ci "Unable to allocate ctxtdata for Kernel ctxt, failing\n"); 1528c2ecf20Sopenharmony_ci kfree(dd->rcd); 1538c2ecf20Sopenharmony_ci dd->rcd = NULL; 1548c2ecf20Sopenharmony_ci return -ENOMEM; 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci rcd->pkeys[0] = QIB_DEFAULT_P_KEY; 1578c2ecf20Sopenharmony_ci rcd->seq_cnt = 1; 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci return 0; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci/* 1638c2ecf20Sopenharmony_ci * Common code for user and kernel context setup. 1648c2ecf20Sopenharmony_ci */ 1658c2ecf20Sopenharmony_cistruct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *ppd, u32 ctxt, 1668c2ecf20Sopenharmony_ci int node_id) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci struct qib_devdata *dd = ppd->dd; 1698c2ecf20Sopenharmony_ci struct qib_ctxtdata *rcd; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci rcd = kzalloc_node(sizeof(*rcd), GFP_KERNEL, node_id); 1728c2ecf20Sopenharmony_ci if (rcd) { 1738c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&rcd->qp_wait_list); 1748c2ecf20Sopenharmony_ci rcd->node_id = node_id; 1758c2ecf20Sopenharmony_ci rcd->ppd = ppd; 1768c2ecf20Sopenharmony_ci rcd->dd = dd; 1778c2ecf20Sopenharmony_ci rcd->cnt = 1; 1788c2ecf20Sopenharmony_ci rcd->ctxt = ctxt; 1798c2ecf20Sopenharmony_ci dd->rcd[ctxt] = rcd; 1808c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 1818c2ecf20Sopenharmony_ci if (ctxt < dd->first_user_ctxt) { /* N/A for PSM contexts */ 1828c2ecf20Sopenharmony_ci rcd->opstats = kzalloc_node(sizeof(*rcd->opstats), 1838c2ecf20Sopenharmony_ci GFP_KERNEL, node_id); 1848c2ecf20Sopenharmony_ci if (!rcd->opstats) { 1858c2ecf20Sopenharmony_ci kfree(rcd); 1868c2ecf20Sopenharmony_ci qib_dev_err(dd, 1878c2ecf20Sopenharmony_ci "Unable to allocate per ctxt stats buffer\n"); 1888c2ecf20Sopenharmony_ci return NULL; 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci#endif 1928c2ecf20Sopenharmony_ci dd->f_init_ctxt(rcd); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci /* 1958c2ecf20Sopenharmony_ci * To avoid wasting a lot of memory, we allocate 32KB chunks 1968c2ecf20Sopenharmony_ci * of physically contiguous memory, advance through it until 1978c2ecf20Sopenharmony_ci * used up and then allocate more. Of course, we need 1988c2ecf20Sopenharmony_ci * memory to store those extra pointers, now. 32KB seems to 1998c2ecf20Sopenharmony_ci * be the most that is "safe" under memory pressure 2008c2ecf20Sopenharmony_ci * (creating large files and then copying them over 2018c2ecf20Sopenharmony_ci * NFS while doing lots of MPI jobs). The OOM killer can 2028c2ecf20Sopenharmony_ci * get invoked, even though we say we can sleep and this can 2038c2ecf20Sopenharmony_ci * cause significant system problems.... 2048c2ecf20Sopenharmony_ci */ 2058c2ecf20Sopenharmony_ci rcd->rcvegrbuf_size = 0x8000; 2068c2ecf20Sopenharmony_ci rcd->rcvegrbufs_perchunk = 2078c2ecf20Sopenharmony_ci rcd->rcvegrbuf_size / dd->rcvegrbufsize; 2088c2ecf20Sopenharmony_ci rcd->rcvegrbuf_chunks = (rcd->rcvegrcnt + 2098c2ecf20Sopenharmony_ci rcd->rcvegrbufs_perchunk - 1) / 2108c2ecf20Sopenharmony_ci rcd->rcvegrbufs_perchunk; 2118c2ecf20Sopenharmony_ci rcd->rcvegrbufs_perchunk_shift = 2128c2ecf20Sopenharmony_ci ilog2(rcd->rcvegrbufs_perchunk); 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci return rcd; 2158c2ecf20Sopenharmony_ci} 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci/* 2188c2ecf20Sopenharmony_ci * Common code for initializing the physical port structure. 2198c2ecf20Sopenharmony_ci */ 2208c2ecf20Sopenharmony_ciint qib_init_pportdata(struct qib_pportdata *ppd, struct qib_devdata *dd, 2218c2ecf20Sopenharmony_ci u8 hw_pidx, u8 port) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci int size; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci ppd->dd = dd; 2268c2ecf20Sopenharmony_ci ppd->hw_pidx = hw_pidx; 2278c2ecf20Sopenharmony_ci ppd->port = port; /* IB port number, not index */ 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci spin_lock_init(&ppd->sdma_lock); 2308c2ecf20Sopenharmony_ci spin_lock_init(&ppd->lflags_lock); 2318c2ecf20Sopenharmony_ci spin_lock_init(&ppd->cc_shadow_lock); 2328c2ecf20Sopenharmony_ci init_waitqueue_head(&ppd->state_wait); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci timer_setup(&ppd->symerr_clear_timer, qib_clear_symerror_on_linkup, 0); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci ppd->qib_wq = NULL; 2378c2ecf20Sopenharmony_ci ppd->ibport_data.pmastats = 2388c2ecf20Sopenharmony_ci alloc_percpu(struct qib_pma_counters); 2398c2ecf20Sopenharmony_ci if (!ppd->ibport_data.pmastats) 2408c2ecf20Sopenharmony_ci return -ENOMEM; 2418c2ecf20Sopenharmony_ci ppd->ibport_data.rvp.rc_acks = alloc_percpu(u64); 2428c2ecf20Sopenharmony_ci ppd->ibport_data.rvp.rc_qacks = alloc_percpu(u64); 2438c2ecf20Sopenharmony_ci ppd->ibport_data.rvp.rc_delayed_comp = alloc_percpu(u64); 2448c2ecf20Sopenharmony_ci if (!(ppd->ibport_data.rvp.rc_acks) || 2458c2ecf20Sopenharmony_ci !(ppd->ibport_data.rvp.rc_qacks) || 2468c2ecf20Sopenharmony_ci !(ppd->ibport_data.rvp.rc_delayed_comp)) 2478c2ecf20Sopenharmony_ci return -ENOMEM; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci if (qib_cc_table_size < IB_CCT_MIN_ENTRIES) 2508c2ecf20Sopenharmony_ci goto bail; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci ppd->cc_supported_table_entries = min(max_t(int, qib_cc_table_size, 2538c2ecf20Sopenharmony_ci IB_CCT_MIN_ENTRIES), IB_CCT_ENTRIES*IB_CC_TABLE_CAP_DEFAULT); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci ppd->cc_max_table_entries = 2568c2ecf20Sopenharmony_ci ppd->cc_supported_table_entries/IB_CCT_ENTRIES; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci size = IB_CC_TABLE_CAP_DEFAULT * sizeof(struct ib_cc_table_entry) 2598c2ecf20Sopenharmony_ci * IB_CCT_ENTRIES; 2608c2ecf20Sopenharmony_ci ppd->ccti_entries = kzalloc(size, GFP_KERNEL); 2618c2ecf20Sopenharmony_ci if (!ppd->ccti_entries) 2628c2ecf20Sopenharmony_ci goto bail; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci size = IB_CC_CCS_ENTRIES * sizeof(struct ib_cc_congestion_entry); 2658c2ecf20Sopenharmony_ci ppd->congestion_entries = kzalloc(size, GFP_KERNEL); 2668c2ecf20Sopenharmony_ci if (!ppd->congestion_entries) 2678c2ecf20Sopenharmony_ci goto bail_1; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci size = sizeof(struct cc_table_shadow); 2708c2ecf20Sopenharmony_ci ppd->ccti_entries_shadow = kzalloc(size, GFP_KERNEL); 2718c2ecf20Sopenharmony_ci if (!ppd->ccti_entries_shadow) 2728c2ecf20Sopenharmony_ci goto bail_2; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci size = sizeof(struct ib_cc_congestion_setting_attr); 2758c2ecf20Sopenharmony_ci ppd->congestion_entries_shadow = kzalloc(size, GFP_KERNEL); 2768c2ecf20Sopenharmony_ci if (!ppd->congestion_entries_shadow) 2778c2ecf20Sopenharmony_ci goto bail_3; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci return 0; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_cibail_3: 2828c2ecf20Sopenharmony_ci kfree(ppd->ccti_entries_shadow); 2838c2ecf20Sopenharmony_ci ppd->ccti_entries_shadow = NULL; 2848c2ecf20Sopenharmony_cibail_2: 2858c2ecf20Sopenharmony_ci kfree(ppd->congestion_entries); 2868c2ecf20Sopenharmony_ci ppd->congestion_entries = NULL; 2878c2ecf20Sopenharmony_cibail_1: 2888c2ecf20Sopenharmony_ci kfree(ppd->ccti_entries); 2898c2ecf20Sopenharmony_ci ppd->ccti_entries = NULL; 2908c2ecf20Sopenharmony_cibail: 2918c2ecf20Sopenharmony_ci /* User is intentionally disabling the congestion control agent */ 2928c2ecf20Sopenharmony_ci if (!qib_cc_table_size) 2938c2ecf20Sopenharmony_ci return 0; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci if (qib_cc_table_size < IB_CCT_MIN_ENTRIES) { 2968c2ecf20Sopenharmony_ci qib_cc_table_size = 0; 2978c2ecf20Sopenharmony_ci qib_dev_err(dd, 2988c2ecf20Sopenharmony_ci "Congestion Control table size %d less than minimum %d for port %d\n", 2998c2ecf20Sopenharmony_ci qib_cc_table_size, IB_CCT_MIN_ENTRIES, port); 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci qib_dev_err(dd, "Congestion Control Agent disabled for port %d\n", 3038c2ecf20Sopenharmony_ci port); 3048c2ecf20Sopenharmony_ci return 0; 3058c2ecf20Sopenharmony_ci} 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cistatic int init_pioavailregs(struct qib_devdata *dd) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci int ret, pidx; 3108c2ecf20Sopenharmony_ci u64 *status_page; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci dd->pioavailregs_dma = dma_alloc_coherent( 3138c2ecf20Sopenharmony_ci &dd->pcidev->dev, PAGE_SIZE, &dd->pioavailregs_phys, 3148c2ecf20Sopenharmony_ci GFP_KERNEL); 3158c2ecf20Sopenharmony_ci if (!dd->pioavailregs_dma) { 3168c2ecf20Sopenharmony_ci qib_dev_err(dd, 3178c2ecf20Sopenharmony_ci "failed to allocate PIOavail reg area in memory\n"); 3188c2ecf20Sopenharmony_ci ret = -ENOMEM; 3198c2ecf20Sopenharmony_ci goto done; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci /* 3238c2ecf20Sopenharmony_ci * We really want L2 cache aligned, but for current CPUs of 3248c2ecf20Sopenharmony_ci * interest, they are the same. 3258c2ecf20Sopenharmony_ci */ 3268c2ecf20Sopenharmony_ci status_page = (u64 *) 3278c2ecf20Sopenharmony_ci ((char *) dd->pioavailregs_dma + 3288c2ecf20Sopenharmony_ci ((2 * L1_CACHE_BYTES + 3298c2ecf20Sopenharmony_ci dd->pioavregs * sizeof(u64)) & ~L1_CACHE_BYTES)); 3308c2ecf20Sopenharmony_ci /* device status comes first, for backwards compatibility */ 3318c2ecf20Sopenharmony_ci dd->devstatusp = status_page; 3328c2ecf20Sopenharmony_ci *status_page++ = 0; 3338c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 3348c2ecf20Sopenharmony_ci dd->pport[pidx].statusp = status_page; 3358c2ecf20Sopenharmony_ci *status_page++ = 0; 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci /* 3398c2ecf20Sopenharmony_ci * Setup buffer to hold freeze and other messages, accessible to 3408c2ecf20Sopenharmony_ci * apps, following statusp. This is per-unit, not per port. 3418c2ecf20Sopenharmony_ci */ 3428c2ecf20Sopenharmony_ci dd->freezemsg = (char *) status_page; 3438c2ecf20Sopenharmony_ci *dd->freezemsg = 0; 3448c2ecf20Sopenharmony_ci /* length of msg buffer is "whatever is left" */ 3458c2ecf20Sopenharmony_ci ret = (char *) status_page - (char *) dd->pioavailregs_dma; 3468c2ecf20Sopenharmony_ci dd->freezelen = PAGE_SIZE - ret; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci ret = 0; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cidone: 3518c2ecf20Sopenharmony_ci return ret; 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci/** 3558c2ecf20Sopenharmony_ci * init_shadow_tids - allocate the shadow TID array 3568c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 3578c2ecf20Sopenharmony_ci * 3588c2ecf20Sopenharmony_ci * allocate the shadow TID array, so we can qib_munlock previous 3598c2ecf20Sopenharmony_ci * entries. It may make more sense to move the pageshadow to the 3608c2ecf20Sopenharmony_ci * ctxt data structure, so we only allocate memory for ctxts actually 3618c2ecf20Sopenharmony_ci * in use, since we at 8k per ctxt, now. 3628c2ecf20Sopenharmony_ci * We don't want failures here to prevent use of the driver/chip, 3638c2ecf20Sopenharmony_ci * so no return value. 3648c2ecf20Sopenharmony_ci */ 3658c2ecf20Sopenharmony_cistatic void init_shadow_tids(struct qib_devdata *dd) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci struct page **pages; 3688c2ecf20Sopenharmony_ci dma_addr_t *addrs; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci pages = vzalloc(array_size(sizeof(struct page *), 3718c2ecf20Sopenharmony_ci dd->cfgctxts * dd->rcvtidcnt)); 3728c2ecf20Sopenharmony_ci if (!pages) 3738c2ecf20Sopenharmony_ci goto bail; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci addrs = vzalloc(array_size(sizeof(dma_addr_t), 3768c2ecf20Sopenharmony_ci dd->cfgctxts * dd->rcvtidcnt)); 3778c2ecf20Sopenharmony_ci if (!addrs) 3788c2ecf20Sopenharmony_ci goto bail_free; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci dd->pageshadow = pages; 3818c2ecf20Sopenharmony_ci dd->physshadow = addrs; 3828c2ecf20Sopenharmony_ci return; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_cibail_free: 3858c2ecf20Sopenharmony_ci vfree(pages); 3868c2ecf20Sopenharmony_cibail: 3878c2ecf20Sopenharmony_ci dd->pageshadow = NULL; 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci/* 3918c2ecf20Sopenharmony_ci * Do initialization for device that is only needed on 3928c2ecf20Sopenharmony_ci * first detect, not on resets. 3938c2ecf20Sopenharmony_ci */ 3948c2ecf20Sopenharmony_cistatic int loadtime_init(struct qib_devdata *dd) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci int ret = 0; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci if (((dd->revision >> QLOGIC_IB_R_SOFTWARE_SHIFT) & 3998c2ecf20Sopenharmony_ci QLOGIC_IB_R_SOFTWARE_MASK) != QIB_CHIP_SWVERSION) { 4008c2ecf20Sopenharmony_ci qib_dev_err(dd, 4018c2ecf20Sopenharmony_ci "Driver only handles version %d, chip swversion is %d (%llx), failing\n", 4028c2ecf20Sopenharmony_ci QIB_CHIP_SWVERSION, 4038c2ecf20Sopenharmony_ci (int)(dd->revision >> 4048c2ecf20Sopenharmony_ci QLOGIC_IB_R_SOFTWARE_SHIFT) & 4058c2ecf20Sopenharmony_ci QLOGIC_IB_R_SOFTWARE_MASK, 4068c2ecf20Sopenharmony_ci (unsigned long long) dd->revision); 4078c2ecf20Sopenharmony_ci ret = -ENOSYS; 4088c2ecf20Sopenharmony_ci goto done; 4098c2ecf20Sopenharmony_ci } 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci if (dd->revision & QLOGIC_IB_R_EMULATOR_MASK) 4128c2ecf20Sopenharmony_ci qib_devinfo(dd->pcidev, "%s", dd->boardversion); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci spin_lock_init(&dd->pioavail_lock); 4158c2ecf20Sopenharmony_ci spin_lock_init(&dd->sendctrl_lock); 4168c2ecf20Sopenharmony_ci spin_lock_init(&dd->uctxt_lock); 4178c2ecf20Sopenharmony_ci spin_lock_init(&dd->qib_diag_trans_lock); 4188c2ecf20Sopenharmony_ci spin_lock_init(&dd->eep_st_lock); 4198c2ecf20Sopenharmony_ci mutex_init(&dd->eep_lock); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci if (qib_mini_init) 4228c2ecf20Sopenharmony_ci goto done; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci ret = init_pioavailregs(dd); 4258c2ecf20Sopenharmony_ci init_shadow_tids(dd); 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci qib_get_eeprom_info(dd); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci /* setup time (don't start yet) to verify we got interrupt */ 4308c2ecf20Sopenharmony_ci timer_setup(&dd->intrchk_timer, verify_interrupt, 0); 4318c2ecf20Sopenharmony_cidone: 4328c2ecf20Sopenharmony_ci return ret; 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci/** 4368c2ecf20Sopenharmony_ci * init_after_reset - re-initialize after a reset 4378c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 4388c2ecf20Sopenharmony_ci * 4398c2ecf20Sopenharmony_ci * sanity check at least some of the values after reset, and 4408c2ecf20Sopenharmony_ci * ensure no receive or transmit (explicitly, in case reset 4418c2ecf20Sopenharmony_ci * failed 4428c2ecf20Sopenharmony_ci */ 4438c2ecf20Sopenharmony_cistatic int init_after_reset(struct qib_devdata *dd) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci int i; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci /* 4488c2ecf20Sopenharmony_ci * Ensure chip does no sends or receives, tail updates, or 4498c2ecf20Sopenharmony_ci * pioavail updates while we re-initialize. This is mostly 4508c2ecf20Sopenharmony_ci * for the driver data structures, not chip registers. 4518c2ecf20Sopenharmony_ci */ 4528c2ecf20Sopenharmony_ci for (i = 0; i < dd->num_pports; ++i) { 4538c2ecf20Sopenharmony_ci /* 4548c2ecf20Sopenharmony_ci * ctxt == -1 means "all contexts". Only really safe for 4558c2ecf20Sopenharmony_ci * _dis_abling things, as here. 4568c2ecf20Sopenharmony_ci */ 4578c2ecf20Sopenharmony_ci dd->f_rcvctrl(dd->pport + i, QIB_RCVCTRL_CTXT_DIS | 4588c2ecf20Sopenharmony_ci QIB_RCVCTRL_INTRAVAIL_DIS | 4598c2ecf20Sopenharmony_ci QIB_RCVCTRL_TAILUPD_DIS, -1); 4608c2ecf20Sopenharmony_ci /* Redundant across ports for some, but no big deal. */ 4618c2ecf20Sopenharmony_ci dd->f_sendctrl(dd->pport + i, QIB_SENDCTRL_SEND_DIS | 4628c2ecf20Sopenharmony_ci QIB_SENDCTRL_AVAIL_DIS); 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci return 0; 4668c2ecf20Sopenharmony_ci} 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_cistatic void enable_chip(struct qib_devdata *dd) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci u64 rcvmask; 4718c2ecf20Sopenharmony_ci int i; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci /* 4748c2ecf20Sopenharmony_ci * Enable PIO send, and update of PIOavail regs to memory. 4758c2ecf20Sopenharmony_ci */ 4768c2ecf20Sopenharmony_ci for (i = 0; i < dd->num_pports; ++i) 4778c2ecf20Sopenharmony_ci dd->f_sendctrl(dd->pport + i, QIB_SENDCTRL_SEND_ENB | 4788c2ecf20Sopenharmony_ci QIB_SENDCTRL_AVAIL_ENB); 4798c2ecf20Sopenharmony_ci /* 4808c2ecf20Sopenharmony_ci * Enable kernel ctxts' receive and receive interrupt. 4818c2ecf20Sopenharmony_ci * Other ctxts done as user opens and inits them. 4828c2ecf20Sopenharmony_ci */ 4838c2ecf20Sopenharmony_ci rcvmask = QIB_RCVCTRL_CTXT_ENB | QIB_RCVCTRL_INTRAVAIL_ENB; 4848c2ecf20Sopenharmony_ci rcvmask |= (dd->flags & QIB_NODMA_RTAIL) ? 4858c2ecf20Sopenharmony_ci QIB_RCVCTRL_TAILUPD_DIS : QIB_RCVCTRL_TAILUPD_ENB; 4868c2ecf20Sopenharmony_ci for (i = 0; dd->rcd && i < dd->first_user_ctxt; ++i) { 4878c2ecf20Sopenharmony_ci struct qib_ctxtdata *rcd = dd->rcd[i]; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci if (rcd) 4908c2ecf20Sopenharmony_ci dd->f_rcvctrl(rcd->ppd, rcvmask, i); 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci} 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_cistatic void verify_interrupt(struct timer_list *t) 4958c2ecf20Sopenharmony_ci{ 4968c2ecf20Sopenharmony_ci struct qib_devdata *dd = from_timer(dd, t, intrchk_timer); 4978c2ecf20Sopenharmony_ci u64 int_counter; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci if (!dd) 5008c2ecf20Sopenharmony_ci return; /* being torn down */ 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci /* 5038c2ecf20Sopenharmony_ci * If we don't have a lid or any interrupts, let the user know and 5048c2ecf20Sopenharmony_ci * don't bother checking again. 5058c2ecf20Sopenharmony_ci */ 5068c2ecf20Sopenharmony_ci int_counter = qib_int_counter(dd) - dd->z_int_counter; 5078c2ecf20Sopenharmony_ci if (int_counter == 0) { 5088c2ecf20Sopenharmony_ci if (!dd->f_intr_fallback(dd)) 5098c2ecf20Sopenharmony_ci dev_err(&dd->pcidev->dev, 5108c2ecf20Sopenharmony_ci "No interrupts detected, not usable.\n"); 5118c2ecf20Sopenharmony_ci else /* re-arm the timer to see if fallback works */ 5128c2ecf20Sopenharmony_ci mod_timer(&dd->intrchk_timer, jiffies + HZ/2); 5138c2ecf20Sopenharmony_ci } 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_cistatic void init_piobuf_state(struct qib_devdata *dd) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci int i, pidx; 5198c2ecf20Sopenharmony_ci u32 uctxts; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci /* 5228c2ecf20Sopenharmony_ci * Ensure all buffers are free, and fifos empty. Buffers 5238c2ecf20Sopenharmony_ci * are common, so only do once for port 0. 5248c2ecf20Sopenharmony_ci * 5258c2ecf20Sopenharmony_ci * After enable and qib_chg_pioavailkernel so we can safely 5268c2ecf20Sopenharmony_ci * enable pioavail updates and PIOENABLE. After this, packets 5278c2ecf20Sopenharmony_ci * are ready and able to go out. 5288c2ecf20Sopenharmony_ci */ 5298c2ecf20Sopenharmony_ci dd->f_sendctrl(dd->pport, QIB_SENDCTRL_DISARM_ALL); 5308c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) 5318c2ecf20Sopenharmony_ci dd->f_sendctrl(dd->pport + pidx, QIB_SENDCTRL_FLUSH); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci /* 5348c2ecf20Sopenharmony_ci * If not all sendbufs are used, add the one to each of the lower 5358c2ecf20Sopenharmony_ci * numbered contexts. pbufsctxt and lastctxt_piobuf are 5368c2ecf20Sopenharmony_ci * calculated in chip-specific code because it may cause some 5378c2ecf20Sopenharmony_ci * chip-specific adjustments to be made. 5388c2ecf20Sopenharmony_ci */ 5398c2ecf20Sopenharmony_ci uctxts = dd->cfgctxts - dd->first_user_ctxt; 5408c2ecf20Sopenharmony_ci dd->ctxts_extrabuf = dd->pbufsctxt ? 5418c2ecf20Sopenharmony_ci dd->lastctxt_piobuf - (dd->pbufsctxt * uctxts) : 0; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci /* 5448c2ecf20Sopenharmony_ci * Set up the shadow copies of the piobufavail registers, 5458c2ecf20Sopenharmony_ci * which we compare against the chip registers for now, and 5468c2ecf20Sopenharmony_ci * the in memory DMA'ed copies of the registers. 5478c2ecf20Sopenharmony_ci * By now pioavail updates to memory should have occurred, so 5488c2ecf20Sopenharmony_ci * copy them into our working/shadow registers; this is in 5498c2ecf20Sopenharmony_ci * case something went wrong with abort, but mostly to get the 5508c2ecf20Sopenharmony_ci * initial values of the generation bit correct. 5518c2ecf20Sopenharmony_ci */ 5528c2ecf20Sopenharmony_ci for (i = 0; i < dd->pioavregs; i++) { 5538c2ecf20Sopenharmony_ci __le64 tmp; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci tmp = dd->pioavailregs_dma[i]; 5568c2ecf20Sopenharmony_ci /* 5578c2ecf20Sopenharmony_ci * Don't need to worry about pioavailkernel here 5588c2ecf20Sopenharmony_ci * because we will call qib_chg_pioavailkernel() later 5598c2ecf20Sopenharmony_ci * in initialization, to busy out buffers as needed. 5608c2ecf20Sopenharmony_ci */ 5618c2ecf20Sopenharmony_ci dd->pioavailshadow[i] = le64_to_cpu(tmp); 5628c2ecf20Sopenharmony_ci } 5638c2ecf20Sopenharmony_ci while (i < ARRAY_SIZE(dd->pioavailshadow)) 5648c2ecf20Sopenharmony_ci dd->pioavailshadow[i++] = 0; /* for debugging sanity */ 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci /* after pioavailshadow is setup */ 5678c2ecf20Sopenharmony_ci qib_chg_pioavailkernel(dd, 0, dd->piobcnt2k + dd->piobcnt4k, 5688c2ecf20Sopenharmony_ci TXCHK_CHG_TYPE_KERN, NULL); 5698c2ecf20Sopenharmony_ci dd->f_initvl15_bufs(dd); 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci/** 5738c2ecf20Sopenharmony_ci * qib_create_workqueues - create per port workqueues 5748c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 5758c2ecf20Sopenharmony_ci */ 5768c2ecf20Sopenharmony_cistatic int qib_create_workqueues(struct qib_devdata *dd) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci int pidx; 5798c2ecf20Sopenharmony_ci struct qib_pportdata *ppd; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 5828c2ecf20Sopenharmony_ci ppd = dd->pport + pidx; 5838c2ecf20Sopenharmony_ci if (!ppd->qib_wq) { 5848c2ecf20Sopenharmony_ci char wq_name[8]; /* 3 + 2 + 1 + 1 + 1 */ 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci snprintf(wq_name, sizeof(wq_name), "qib%d_%d", 5878c2ecf20Sopenharmony_ci dd->unit, pidx); 5888c2ecf20Sopenharmony_ci ppd->qib_wq = alloc_ordered_workqueue(wq_name, 5898c2ecf20Sopenharmony_ci WQ_MEM_RECLAIM); 5908c2ecf20Sopenharmony_ci if (!ppd->qib_wq) 5918c2ecf20Sopenharmony_ci goto wq_error; 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci } 5948c2ecf20Sopenharmony_ci return 0; 5958c2ecf20Sopenharmony_ciwq_error: 5968c2ecf20Sopenharmony_ci pr_err("create_singlethread_workqueue failed for port %d\n", 5978c2ecf20Sopenharmony_ci pidx + 1); 5988c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 5998c2ecf20Sopenharmony_ci ppd = dd->pport + pidx; 6008c2ecf20Sopenharmony_ci if (ppd->qib_wq) { 6018c2ecf20Sopenharmony_ci destroy_workqueue(ppd->qib_wq); 6028c2ecf20Sopenharmony_ci ppd->qib_wq = NULL; 6038c2ecf20Sopenharmony_ci } 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci return -ENOMEM; 6068c2ecf20Sopenharmony_ci} 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_cistatic void qib_free_pportdata(struct qib_pportdata *ppd) 6098c2ecf20Sopenharmony_ci{ 6108c2ecf20Sopenharmony_ci free_percpu(ppd->ibport_data.pmastats); 6118c2ecf20Sopenharmony_ci free_percpu(ppd->ibport_data.rvp.rc_acks); 6128c2ecf20Sopenharmony_ci free_percpu(ppd->ibport_data.rvp.rc_qacks); 6138c2ecf20Sopenharmony_ci free_percpu(ppd->ibport_data.rvp.rc_delayed_comp); 6148c2ecf20Sopenharmony_ci ppd->ibport_data.pmastats = NULL; 6158c2ecf20Sopenharmony_ci} 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci/** 6188c2ecf20Sopenharmony_ci * qib_init - do the actual initialization sequence on the chip 6198c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 6208c2ecf20Sopenharmony_ci * @reinit: reinitializing, so don't allocate new memory 6218c2ecf20Sopenharmony_ci * 6228c2ecf20Sopenharmony_ci * Do the actual initialization sequence on the chip. This is done 6238c2ecf20Sopenharmony_ci * both from the init routine called from the PCI infrastructure, and 6248c2ecf20Sopenharmony_ci * when we reset the chip, or detect that it was reset internally, 6258c2ecf20Sopenharmony_ci * or it's administratively re-enabled. 6268c2ecf20Sopenharmony_ci * 6278c2ecf20Sopenharmony_ci * Memory allocation here and in called routines is only done in 6288c2ecf20Sopenharmony_ci * the first case (reinit == 0). We have to be careful, because even 6298c2ecf20Sopenharmony_ci * without memory allocation, we need to re-write all the chip registers 6308c2ecf20Sopenharmony_ci * TIDs, etc. after the reset or enable has completed. 6318c2ecf20Sopenharmony_ci */ 6328c2ecf20Sopenharmony_ciint qib_init(struct qib_devdata *dd, int reinit) 6338c2ecf20Sopenharmony_ci{ 6348c2ecf20Sopenharmony_ci int ret = 0, pidx, lastfail = 0; 6358c2ecf20Sopenharmony_ci u32 portok = 0; 6368c2ecf20Sopenharmony_ci unsigned i; 6378c2ecf20Sopenharmony_ci struct qib_ctxtdata *rcd; 6388c2ecf20Sopenharmony_ci struct qib_pportdata *ppd; 6398c2ecf20Sopenharmony_ci unsigned long flags; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci /* Set linkstate to unknown, so we can watch for a transition. */ 6428c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 6438c2ecf20Sopenharmony_ci ppd = dd->pport + pidx; 6448c2ecf20Sopenharmony_ci spin_lock_irqsave(&ppd->lflags_lock, flags); 6458c2ecf20Sopenharmony_ci ppd->lflags &= ~(QIBL_LINKACTIVE | QIBL_LINKARMED | 6468c2ecf20Sopenharmony_ci QIBL_LINKDOWN | QIBL_LINKINIT | 6478c2ecf20Sopenharmony_ci QIBL_LINKV); 6488c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ppd->lflags_lock, flags); 6498c2ecf20Sopenharmony_ci } 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci if (reinit) 6528c2ecf20Sopenharmony_ci ret = init_after_reset(dd); 6538c2ecf20Sopenharmony_ci else 6548c2ecf20Sopenharmony_ci ret = loadtime_init(dd); 6558c2ecf20Sopenharmony_ci if (ret) 6568c2ecf20Sopenharmony_ci goto done; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci /* Bypass most chip-init, to get to device creation */ 6598c2ecf20Sopenharmony_ci if (qib_mini_init) 6608c2ecf20Sopenharmony_ci return 0; 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci ret = dd->f_late_initreg(dd); 6638c2ecf20Sopenharmony_ci if (ret) 6648c2ecf20Sopenharmony_ci goto done; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci /* dd->rcd can be NULL if early init failed */ 6678c2ecf20Sopenharmony_ci for (i = 0; dd->rcd && i < dd->first_user_ctxt; ++i) { 6688c2ecf20Sopenharmony_ci /* 6698c2ecf20Sopenharmony_ci * Set up the (kernel) rcvhdr queue and egr TIDs. If doing 6708c2ecf20Sopenharmony_ci * re-init, the simplest way to handle this is to free 6718c2ecf20Sopenharmony_ci * existing, and re-allocate. 6728c2ecf20Sopenharmony_ci * Need to re-create rest of ctxt 0 ctxtdata as well. 6738c2ecf20Sopenharmony_ci */ 6748c2ecf20Sopenharmony_ci rcd = dd->rcd[i]; 6758c2ecf20Sopenharmony_ci if (!rcd) 6768c2ecf20Sopenharmony_ci continue; 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci lastfail = qib_create_rcvhdrq(dd, rcd); 6798c2ecf20Sopenharmony_ci if (!lastfail) 6808c2ecf20Sopenharmony_ci lastfail = qib_setup_eagerbufs(rcd); 6818c2ecf20Sopenharmony_ci if (lastfail) 6828c2ecf20Sopenharmony_ci qib_dev_err(dd, 6838c2ecf20Sopenharmony_ci "failed to allocate kernel ctxt's rcvhdrq and/or egr bufs\n"); 6848c2ecf20Sopenharmony_ci } 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 6878c2ecf20Sopenharmony_ci int mtu; 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci if (lastfail) 6908c2ecf20Sopenharmony_ci ret = lastfail; 6918c2ecf20Sopenharmony_ci ppd = dd->pport + pidx; 6928c2ecf20Sopenharmony_ci mtu = ib_mtu_enum_to_int(qib_ibmtu); 6938c2ecf20Sopenharmony_ci if (mtu == -1) { 6948c2ecf20Sopenharmony_ci mtu = QIB_DEFAULT_MTU; 6958c2ecf20Sopenharmony_ci qib_ibmtu = 0; /* don't leave invalid value */ 6968c2ecf20Sopenharmony_ci } 6978c2ecf20Sopenharmony_ci /* set max we can ever have for this driver load */ 6988c2ecf20Sopenharmony_ci ppd->init_ibmaxlen = min(mtu > 2048 ? 6998c2ecf20Sopenharmony_ci dd->piosize4k : dd->piosize2k, 7008c2ecf20Sopenharmony_ci dd->rcvegrbufsize + 7018c2ecf20Sopenharmony_ci (dd->rcvhdrentsize << 2)); 7028c2ecf20Sopenharmony_ci /* 7038c2ecf20Sopenharmony_ci * Have to initialize ibmaxlen, but this will normally 7048c2ecf20Sopenharmony_ci * change immediately in qib_set_mtu(). 7058c2ecf20Sopenharmony_ci */ 7068c2ecf20Sopenharmony_ci ppd->ibmaxlen = ppd->init_ibmaxlen; 7078c2ecf20Sopenharmony_ci qib_set_mtu(ppd, mtu); 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci spin_lock_irqsave(&ppd->lflags_lock, flags); 7108c2ecf20Sopenharmony_ci ppd->lflags |= QIBL_IB_LINK_DISABLED; 7118c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ppd->lflags_lock, flags); 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci lastfail = dd->f_bringup_serdes(ppd); 7148c2ecf20Sopenharmony_ci if (lastfail) { 7158c2ecf20Sopenharmony_ci qib_devinfo(dd->pcidev, 7168c2ecf20Sopenharmony_ci "Failed to bringup IB port %u\n", ppd->port); 7178c2ecf20Sopenharmony_ci lastfail = -ENETDOWN; 7188c2ecf20Sopenharmony_ci continue; 7198c2ecf20Sopenharmony_ci } 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci portok++; 7228c2ecf20Sopenharmony_ci } 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci if (!portok) { 7258c2ecf20Sopenharmony_ci /* none of the ports initialized */ 7268c2ecf20Sopenharmony_ci if (!ret && lastfail) 7278c2ecf20Sopenharmony_ci ret = lastfail; 7288c2ecf20Sopenharmony_ci else if (!ret) 7298c2ecf20Sopenharmony_ci ret = -ENETDOWN; 7308c2ecf20Sopenharmony_ci /* but continue on, so we can debug cause */ 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci enable_chip(dd); 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci init_piobuf_state(dd); 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_cidone: 7388c2ecf20Sopenharmony_ci if (!ret) { 7398c2ecf20Sopenharmony_ci /* chip is OK for user apps; mark it as initialized */ 7408c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 7418c2ecf20Sopenharmony_ci ppd = dd->pport + pidx; 7428c2ecf20Sopenharmony_ci /* 7438c2ecf20Sopenharmony_ci * Set status even if port serdes is not initialized 7448c2ecf20Sopenharmony_ci * so that diags will work. 7458c2ecf20Sopenharmony_ci */ 7468c2ecf20Sopenharmony_ci *ppd->statusp |= QIB_STATUS_CHIP_PRESENT | 7478c2ecf20Sopenharmony_ci QIB_STATUS_INITTED; 7488c2ecf20Sopenharmony_ci if (!ppd->link_speed_enabled) 7498c2ecf20Sopenharmony_ci continue; 7508c2ecf20Sopenharmony_ci if (dd->flags & QIB_HAS_SEND_DMA) 7518c2ecf20Sopenharmony_ci ret = qib_setup_sdma(ppd); 7528c2ecf20Sopenharmony_ci timer_setup(&ppd->hol_timer, qib_hol_event, 0); 7538c2ecf20Sopenharmony_ci ppd->hol_state = QIB_HOL_UP; 7548c2ecf20Sopenharmony_ci } 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci /* now we can enable all interrupts from the chip */ 7578c2ecf20Sopenharmony_ci dd->f_set_intr_state(dd, 1); 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci /* 7608c2ecf20Sopenharmony_ci * Setup to verify we get an interrupt, and fallback 7618c2ecf20Sopenharmony_ci * to an alternate if necessary and possible. 7628c2ecf20Sopenharmony_ci */ 7638c2ecf20Sopenharmony_ci mod_timer(&dd->intrchk_timer, jiffies + HZ/2); 7648c2ecf20Sopenharmony_ci /* start stats retrieval timer */ 7658c2ecf20Sopenharmony_ci mod_timer(&dd->stats_timer, jiffies + HZ * ACTIVITY_TIMER); 7668c2ecf20Sopenharmony_ci } 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci /* if ret is non-zero, we probably should do some cleanup here... */ 7698c2ecf20Sopenharmony_ci return ret; 7708c2ecf20Sopenharmony_ci} 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci/* 7738c2ecf20Sopenharmony_ci * These next two routines are placeholders in case we don't have per-arch 7748c2ecf20Sopenharmony_ci * code for controlling write combining. If explicit control of write 7758c2ecf20Sopenharmony_ci * combining is not available, performance will probably be awful. 7768c2ecf20Sopenharmony_ci */ 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ciint __attribute__((weak)) qib_enable_wc(struct qib_devdata *dd) 7798c2ecf20Sopenharmony_ci{ 7808c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 7818c2ecf20Sopenharmony_ci} 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_civoid __attribute__((weak)) qib_disable_wc(struct qib_devdata *dd) 7848c2ecf20Sopenharmony_ci{ 7858c2ecf20Sopenharmony_ci} 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_cistruct qib_devdata *qib_lookup(int unit) 7888c2ecf20Sopenharmony_ci{ 7898c2ecf20Sopenharmony_ci return xa_load(&qib_dev_table, unit); 7908c2ecf20Sopenharmony_ci} 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci/* 7938c2ecf20Sopenharmony_ci * Stop the timers during unit shutdown, or after an error late 7948c2ecf20Sopenharmony_ci * in initialization. 7958c2ecf20Sopenharmony_ci */ 7968c2ecf20Sopenharmony_cistatic void qib_stop_timers(struct qib_devdata *dd) 7978c2ecf20Sopenharmony_ci{ 7988c2ecf20Sopenharmony_ci struct qib_pportdata *ppd; 7998c2ecf20Sopenharmony_ci int pidx; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci if (dd->stats_timer.function) 8028c2ecf20Sopenharmony_ci del_timer_sync(&dd->stats_timer); 8038c2ecf20Sopenharmony_ci if (dd->intrchk_timer.function) 8048c2ecf20Sopenharmony_ci del_timer_sync(&dd->intrchk_timer); 8058c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 8068c2ecf20Sopenharmony_ci ppd = dd->pport + pidx; 8078c2ecf20Sopenharmony_ci if (ppd->hol_timer.function) 8088c2ecf20Sopenharmony_ci del_timer_sync(&ppd->hol_timer); 8098c2ecf20Sopenharmony_ci if (ppd->led_override_timer.function) { 8108c2ecf20Sopenharmony_ci del_timer_sync(&ppd->led_override_timer); 8118c2ecf20Sopenharmony_ci atomic_set(&ppd->led_override_timer_active, 0); 8128c2ecf20Sopenharmony_ci } 8138c2ecf20Sopenharmony_ci if (ppd->symerr_clear_timer.function) 8148c2ecf20Sopenharmony_ci del_timer_sync(&ppd->symerr_clear_timer); 8158c2ecf20Sopenharmony_ci } 8168c2ecf20Sopenharmony_ci} 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci/** 8198c2ecf20Sopenharmony_ci * qib_shutdown_device - shut down a device 8208c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 8218c2ecf20Sopenharmony_ci * 8228c2ecf20Sopenharmony_ci * This is called to make the device quiet when we are about to 8238c2ecf20Sopenharmony_ci * unload the driver, and also when the device is administratively 8248c2ecf20Sopenharmony_ci * disabled. It does not free any data structures. 8258c2ecf20Sopenharmony_ci * Everything it does has to be setup again by qib_init(dd, 1) 8268c2ecf20Sopenharmony_ci */ 8278c2ecf20Sopenharmony_cistatic void qib_shutdown_device(struct qib_devdata *dd) 8288c2ecf20Sopenharmony_ci{ 8298c2ecf20Sopenharmony_ci struct qib_pportdata *ppd; 8308c2ecf20Sopenharmony_ci unsigned pidx; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci if (dd->flags & QIB_SHUTDOWN) 8338c2ecf20Sopenharmony_ci return; 8348c2ecf20Sopenharmony_ci dd->flags |= QIB_SHUTDOWN; 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 8378c2ecf20Sopenharmony_ci ppd = dd->pport + pidx; 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci spin_lock_irq(&ppd->lflags_lock); 8408c2ecf20Sopenharmony_ci ppd->lflags &= ~(QIBL_LINKDOWN | QIBL_LINKINIT | 8418c2ecf20Sopenharmony_ci QIBL_LINKARMED | QIBL_LINKACTIVE | 8428c2ecf20Sopenharmony_ci QIBL_LINKV); 8438c2ecf20Sopenharmony_ci spin_unlock_irq(&ppd->lflags_lock); 8448c2ecf20Sopenharmony_ci *ppd->statusp &= ~(QIB_STATUS_IB_CONF | QIB_STATUS_IB_READY); 8458c2ecf20Sopenharmony_ci } 8468c2ecf20Sopenharmony_ci dd->flags &= ~QIB_INITTED; 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci /* mask interrupts, but not errors */ 8498c2ecf20Sopenharmony_ci dd->f_set_intr_state(dd, 0); 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 8528c2ecf20Sopenharmony_ci ppd = dd->pport + pidx; 8538c2ecf20Sopenharmony_ci dd->f_rcvctrl(ppd, QIB_RCVCTRL_TAILUPD_DIS | 8548c2ecf20Sopenharmony_ci QIB_RCVCTRL_CTXT_DIS | 8558c2ecf20Sopenharmony_ci QIB_RCVCTRL_INTRAVAIL_DIS | 8568c2ecf20Sopenharmony_ci QIB_RCVCTRL_PKEY_ENB, -1); 8578c2ecf20Sopenharmony_ci /* 8588c2ecf20Sopenharmony_ci * Gracefully stop all sends allowing any in progress to 8598c2ecf20Sopenharmony_ci * trickle out first. 8608c2ecf20Sopenharmony_ci */ 8618c2ecf20Sopenharmony_ci dd->f_sendctrl(ppd, QIB_SENDCTRL_CLEAR); 8628c2ecf20Sopenharmony_ci } 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci /* 8658c2ecf20Sopenharmony_ci * Enough for anything that's going to trickle out to have actually 8668c2ecf20Sopenharmony_ci * done so. 8678c2ecf20Sopenharmony_ci */ 8688c2ecf20Sopenharmony_ci udelay(20); 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 8718c2ecf20Sopenharmony_ci ppd = dd->pport + pidx; 8728c2ecf20Sopenharmony_ci dd->f_setextled(ppd, 0); /* make sure LEDs are off */ 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci if (dd->flags & QIB_HAS_SEND_DMA) 8758c2ecf20Sopenharmony_ci qib_teardown_sdma(ppd); 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci dd->f_sendctrl(ppd, QIB_SENDCTRL_AVAIL_DIS | 8788c2ecf20Sopenharmony_ci QIB_SENDCTRL_SEND_DIS); 8798c2ecf20Sopenharmony_ci /* 8808c2ecf20Sopenharmony_ci * Clear SerdesEnable. 8818c2ecf20Sopenharmony_ci * We can't count on interrupts since we are stopping. 8828c2ecf20Sopenharmony_ci */ 8838c2ecf20Sopenharmony_ci dd->f_quiet_serdes(ppd); 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci if (ppd->qib_wq) { 8868c2ecf20Sopenharmony_ci destroy_workqueue(ppd->qib_wq); 8878c2ecf20Sopenharmony_ci ppd->qib_wq = NULL; 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci qib_free_pportdata(ppd); 8908c2ecf20Sopenharmony_ci } 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci} 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci/** 8958c2ecf20Sopenharmony_ci * qib_free_ctxtdata - free a context's allocated data 8968c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 8978c2ecf20Sopenharmony_ci * @rcd: the ctxtdata structure 8988c2ecf20Sopenharmony_ci * 8998c2ecf20Sopenharmony_ci * free up any allocated data for a context 9008c2ecf20Sopenharmony_ci * This should not touch anything that would affect a simultaneous 9018c2ecf20Sopenharmony_ci * re-allocation of context data, because it is called after qib_mutex 9028c2ecf20Sopenharmony_ci * is released (and can be called from reinit as well). 9038c2ecf20Sopenharmony_ci * It should never change any chip state, or global driver state. 9048c2ecf20Sopenharmony_ci */ 9058c2ecf20Sopenharmony_civoid qib_free_ctxtdata(struct qib_devdata *dd, struct qib_ctxtdata *rcd) 9068c2ecf20Sopenharmony_ci{ 9078c2ecf20Sopenharmony_ci if (!rcd) 9088c2ecf20Sopenharmony_ci return; 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci if (rcd->rcvhdrq) { 9118c2ecf20Sopenharmony_ci dma_free_coherent(&dd->pcidev->dev, rcd->rcvhdrq_size, 9128c2ecf20Sopenharmony_ci rcd->rcvhdrq, rcd->rcvhdrq_phys); 9138c2ecf20Sopenharmony_ci rcd->rcvhdrq = NULL; 9148c2ecf20Sopenharmony_ci if (rcd->rcvhdrtail_kvaddr) { 9158c2ecf20Sopenharmony_ci dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE, 9168c2ecf20Sopenharmony_ci rcd->rcvhdrtail_kvaddr, 9178c2ecf20Sopenharmony_ci rcd->rcvhdrqtailaddr_phys); 9188c2ecf20Sopenharmony_ci rcd->rcvhdrtail_kvaddr = NULL; 9198c2ecf20Sopenharmony_ci } 9208c2ecf20Sopenharmony_ci } 9218c2ecf20Sopenharmony_ci if (rcd->rcvegrbuf) { 9228c2ecf20Sopenharmony_ci unsigned e; 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci for (e = 0; e < rcd->rcvegrbuf_chunks; e++) { 9258c2ecf20Sopenharmony_ci void *base = rcd->rcvegrbuf[e]; 9268c2ecf20Sopenharmony_ci size_t size = rcd->rcvegrbuf_size; 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci dma_free_coherent(&dd->pcidev->dev, size, 9298c2ecf20Sopenharmony_ci base, rcd->rcvegrbuf_phys[e]); 9308c2ecf20Sopenharmony_ci } 9318c2ecf20Sopenharmony_ci kfree(rcd->rcvegrbuf); 9328c2ecf20Sopenharmony_ci rcd->rcvegrbuf = NULL; 9338c2ecf20Sopenharmony_ci kfree(rcd->rcvegrbuf_phys); 9348c2ecf20Sopenharmony_ci rcd->rcvegrbuf_phys = NULL; 9358c2ecf20Sopenharmony_ci rcd->rcvegrbuf_chunks = 0; 9368c2ecf20Sopenharmony_ci } 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci kfree(rcd->tid_pg_list); 9398c2ecf20Sopenharmony_ci vfree(rcd->user_event_mask); 9408c2ecf20Sopenharmony_ci vfree(rcd->subctxt_uregbase); 9418c2ecf20Sopenharmony_ci vfree(rcd->subctxt_rcvegrbuf); 9428c2ecf20Sopenharmony_ci vfree(rcd->subctxt_rcvhdr_base); 9438c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 9448c2ecf20Sopenharmony_ci kfree(rcd->opstats); 9458c2ecf20Sopenharmony_ci rcd->opstats = NULL; 9468c2ecf20Sopenharmony_ci#endif 9478c2ecf20Sopenharmony_ci kfree(rcd); 9488c2ecf20Sopenharmony_ci} 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci/* 9518c2ecf20Sopenharmony_ci * Perform a PIO buffer bandwidth write test, to verify proper system 9528c2ecf20Sopenharmony_ci * configuration. Even when all the setup calls work, occasionally 9538c2ecf20Sopenharmony_ci * BIOS or other issues can prevent write combining from working, or 9548c2ecf20Sopenharmony_ci * can cause other bandwidth problems to the chip. 9558c2ecf20Sopenharmony_ci * 9568c2ecf20Sopenharmony_ci * This test simply writes the same buffer over and over again, and 9578c2ecf20Sopenharmony_ci * measures close to the peak bandwidth to the chip (not testing 9588c2ecf20Sopenharmony_ci * data bandwidth to the wire). On chips that use an address-based 9598c2ecf20Sopenharmony_ci * trigger to send packets to the wire, this is easy. On chips that 9608c2ecf20Sopenharmony_ci * use a count to trigger, we want to make sure that the packet doesn't 9618c2ecf20Sopenharmony_ci * go out on the wire, or trigger flow control checks. 9628c2ecf20Sopenharmony_ci */ 9638c2ecf20Sopenharmony_cistatic void qib_verify_pioperf(struct qib_devdata *dd) 9648c2ecf20Sopenharmony_ci{ 9658c2ecf20Sopenharmony_ci u32 pbnum, cnt, lcnt; 9668c2ecf20Sopenharmony_ci u32 __iomem *piobuf; 9678c2ecf20Sopenharmony_ci u32 *addr; 9688c2ecf20Sopenharmony_ci u64 msecs, emsecs; 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci piobuf = dd->f_getsendbuf(dd->pport, 0ULL, &pbnum); 9718c2ecf20Sopenharmony_ci if (!piobuf) { 9728c2ecf20Sopenharmony_ci qib_devinfo(dd->pcidev, 9738c2ecf20Sopenharmony_ci "No PIObufs for checking perf, skipping\n"); 9748c2ecf20Sopenharmony_ci return; 9758c2ecf20Sopenharmony_ci } 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci /* 9788c2ecf20Sopenharmony_ci * Enough to give us a reasonable test, less than piobuf size, and 9798c2ecf20Sopenharmony_ci * likely multiple of store buffer length. 9808c2ecf20Sopenharmony_ci */ 9818c2ecf20Sopenharmony_ci cnt = 1024; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci addr = vmalloc(cnt); 9848c2ecf20Sopenharmony_ci if (!addr) 9858c2ecf20Sopenharmony_ci goto done; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci preempt_disable(); /* we want reasonably accurate elapsed time */ 9888c2ecf20Sopenharmony_ci msecs = 1 + jiffies_to_msecs(jiffies); 9898c2ecf20Sopenharmony_ci for (lcnt = 0; lcnt < 10000U; lcnt++) { 9908c2ecf20Sopenharmony_ci /* wait until we cross msec boundary */ 9918c2ecf20Sopenharmony_ci if (jiffies_to_msecs(jiffies) >= msecs) 9928c2ecf20Sopenharmony_ci break; 9938c2ecf20Sopenharmony_ci udelay(1); 9948c2ecf20Sopenharmony_ci } 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci dd->f_set_armlaunch(dd, 0); 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci /* 9998c2ecf20Sopenharmony_ci * length 0, no dwords actually sent 10008c2ecf20Sopenharmony_ci */ 10018c2ecf20Sopenharmony_ci writeq(0, piobuf); 10028c2ecf20Sopenharmony_ci qib_flush_wc(); 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci /* 10058c2ecf20Sopenharmony_ci * This is only roughly accurate, since even with preempt we 10068c2ecf20Sopenharmony_ci * still take interrupts that could take a while. Running for 10078c2ecf20Sopenharmony_ci * >= 5 msec seems to get us "close enough" to accurate values. 10088c2ecf20Sopenharmony_ci */ 10098c2ecf20Sopenharmony_ci msecs = jiffies_to_msecs(jiffies); 10108c2ecf20Sopenharmony_ci for (emsecs = lcnt = 0; emsecs <= 5UL; lcnt++) { 10118c2ecf20Sopenharmony_ci qib_pio_copy(piobuf + 64, addr, cnt >> 2); 10128c2ecf20Sopenharmony_ci emsecs = jiffies_to_msecs(jiffies) - msecs; 10138c2ecf20Sopenharmony_ci } 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci /* 1 GiB/sec, slightly over IB SDR line rate */ 10168c2ecf20Sopenharmony_ci if (lcnt < (emsecs * 1024U)) 10178c2ecf20Sopenharmony_ci qib_dev_err(dd, 10188c2ecf20Sopenharmony_ci "Performance problem: bandwidth to PIO buffers is only %u MiB/sec\n", 10198c2ecf20Sopenharmony_ci lcnt / (u32) emsecs); 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci preempt_enable(); 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci vfree(addr); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_cidone: 10268c2ecf20Sopenharmony_ci /* disarm piobuf, so it's available again */ 10278c2ecf20Sopenharmony_ci dd->f_sendctrl(dd->pport, QIB_SENDCTRL_DISARM_BUF(pbnum)); 10288c2ecf20Sopenharmony_ci qib_sendbuf_done(dd, pbnum); 10298c2ecf20Sopenharmony_ci dd->f_set_armlaunch(dd, 1); 10308c2ecf20Sopenharmony_ci} 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_civoid qib_free_devdata(struct qib_devdata *dd) 10338c2ecf20Sopenharmony_ci{ 10348c2ecf20Sopenharmony_ci unsigned long flags; 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci xa_lock_irqsave(&qib_dev_table, flags); 10378c2ecf20Sopenharmony_ci __xa_erase(&qib_dev_table, dd->unit); 10388c2ecf20Sopenharmony_ci xa_unlock_irqrestore(&qib_dev_table, flags); 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 10418c2ecf20Sopenharmony_ci qib_dbg_ibdev_exit(&dd->verbs_dev); 10428c2ecf20Sopenharmony_ci#endif 10438c2ecf20Sopenharmony_ci free_percpu(dd->int_counter); 10448c2ecf20Sopenharmony_ci rvt_dealloc_device(&dd->verbs_dev.rdi); 10458c2ecf20Sopenharmony_ci} 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ciu64 qib_int_counter(struct qib_devdata *dd) 10488c2ecf20Sopenharmony_ci{ 10498c2ecf20Sopenharmony_ci int cpu; 10508c2ecf20Sopenharmony_ci u64 int_counter = 0; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci for_each_possible_cpu(cpu) 10538c2ecf20Sopenharmony_ci int_counter += *per_cpu_ptr(dd->int_counter, cpu); 10548c2ecf20Sopenharmony_ci return int_counter; 10558c2ecf20Sopenharmony_ci} 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ciu64 qib_sps_ints(void) 10588c2ecf20Sopenharmony_ci{ 10598c2ecf20Sopenharmony_ci unsigned long index, flags; 10608c2ecf20Sopenharmony_ci struct qib_devdata *dd; 10618c2ecf20Sopenharmony_ci u64 sps_ints = 0; 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci xa_lock_irqsave(&qib_dev_table, flags); 10648c2ecf20Sopenharmony_ci xa_for_each(&qib_dev_table, index, dd) { 10658c2ecf20Sopenharmony_ci sps_ints += qib_int_counter(dd); 10668c2ecf20Sopenharmony_ci } 10678c2ecf20Sopenharmony_ci xa_unlock_irqrestore(&qib_dev_table, flags); 10688c2ecf20Sopenharmony_ci return sps_ints; 10698c2ecf20Sopenharmony_ci} 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci/* 10728c2ecf20Sopenharmony_ci * Allocate our primary per-unit data structure. Must be done via verbs 10738c2ecf20Sopenharmony_ci * allocator, because the verbs cleanup process both does cleanup and 10748c2ecf20Sopenharmony_ci * free of the data structure. 10758c2ecf20Sopenharmony_ci * "extra" is for chip-specific data. 10768c2ecf20Sopenharmony_ci */ 10778c2ecf20Sopenharmony_cistruct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra) 10788c2ecf20Sopenharmony_ci{ 10798c2ecf20Sopenharmony_ci struct qib_devdata *dd; 10808c2ecf20Sopenharmony_ci int ret, nports; 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci /* extra is * number of ports */ 10838c2ecf20Sopenharmony_ci nports = extra / sizeof(struct qib_pportdata); 10848c2ecf20Sopenharmony_ci dd = (struct qib_devdata *)rvt_alloc_device(sizeof(*dd) + extra, 10858c2ecf20Sopenharmony_ci nports); 10868c2ecf20Sopenharmony_ci if (!dd) 10878c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci ret = xa_alloc_irq(&qib_dev_table, &dd->unit, dd, xa_limit_32b, 10908c2ecf20Sopenharmony_ci GFP_KERNEL); 10918c2ecf20Sopenharmony_ci if (ret < 0) { 10928c2ecf20Sopenharmony_ci qib_early_err(&pdev->dev, 10938c2ecf20Sopenharmony_ci "Could not allocate unit ID: error %d\n", -ret); 10948c2ecf20Sopenharmony_ci goto bail; 10958c2ecf20Sopenharmony_ci } 10968c2ecf20Sopenharmony_ci rvt_set_ibdev_name(&dd->verbs_dev.rdi, "%s%d", "qib", dd->unit); 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci dd->int_counter = alloc_percpu(u64); 10998c2ecf20Sopenharmony_ci if (!dd->int_counter) { 11008c2ecf20Sopenharmony_ci ret = -ENOMEM; 11018c2ecf20Sopenharmony_ci qib_early_err(&pdev->dev, 11028c2ecf20Sopenharmony_ci "Could not allocate per-cpu int_counter\n"); 11038c2ecf20Sopenharmony_ci goto bail; 11048c2ecf20Sopenharmony_ci } 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci if (!qib_cpulist_count) { 11078c2ecf20Sopenharmony_ci u32 count = num_online_cpus(); 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci qib_cpulist = kcalloc(BITS_TO_LONGS(count), sizeof(long), 11108c2ecf20Sopenharmony_ci GFP_KERNEL); 11118c2ecf20Sopenharmony_ci if (qib_cpulist) 11128c2ecf20Sopenharmony_ci qib_cpulist_count = count; 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 11158c2ecf20Sopenharmony_ci qib_dbg_ibdev_init(&dd->verbs_dev); 11168c2ecf20Sopenharmony_ci#endif 11178c2ecf20Sopenharmony_ci return dd; 11188c2ecf20Sopenharmony_cibail: 11198c2ecf20Sopenharmony_ci if (!list_empty(&dd->list)) 11208c2ecf20Sopenharmony_ci list_del_init(&dd->list); 11218c2ecf20Sopenharmony_ci rvt_dealloc_device(&dd->verbs_dev.rdi); 11228c2ecf20Sopenharmony_ci return ERR_PTR(ret); 11238c2ecf20Sopenharmony_ci} 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci/* 11268c2ecf20Sopenharmony_ci * Called from freeze mode handlers, and from PCI error 11278c2ecf20Sopenharmony_ci * reporting code. Should be paranoid about state of 11288c2ecf20Sopenharmony_ci * system and data structures. 11298c2ecf20Sopenharmony_ci */ 11308c2ecf20Sopenharmony_civoid qib_disable_after_error(struct qib_devdata *dd) 11318c2ecf20Sopenharmony_ci{ 11328c2ecf20Sopenharmony_ci if (dd->flags & QIB_INITTED) { 11338c2ecf20Sopenharmony_ci u32 pidx; 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci dd->flags &= ~QIB_INITTED; 11368c2ecf20Sopenharmony_ci if (dd->pport) 11378c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 11388c2ecf20Sopenharmony_ci struct qib_pportdata *ppd; 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci ppd = dd->pport + pidx; 11418c2ecf20Sopenharmony_ci if (dd->flags & QIB_PRESENT) { 11428c2ecf20Sopenharmony_ci qib_set_linkstate(ppd, 11438c2ecf20Sopenharmony_ci QIB_IB_LINKDOWN_DISABLE); 11448c2ecf20Sopenharmony_ci dd->f_setextled(ppd, 0); 11458c2ecf20Sopenharmony_ci } 11468c2ecf20Sopenharmony_ci *ppd->statusp &= ~QIB_STATUS_IB_READY; 11478c2ecf20Sopenharmony_ci } 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci /* 11518c2ecf20Sopenharmony_ci * Mark as having had an error for driver, and also 11528c2ecf20Sopenharmony_ci * for /sys and status word mapped to user programs. 11538c2ecf20Sopenharmony_ci * This marks unit as not usable, until reset. 11548c2ecf20Sopenharmony_ci */ 11558c2ecf20Sopenharmony_ci if (dd->devstatusp) 11568c2ecf20Sopenharmony_ci *dd->devstatusp |= QIB_STATUS_HWERROR; 11578c2ecf20Sopenharmony_ci} 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_cistatic void qib_remove_one(struct pci_dev *); 11608c2ecf20Sopenharmony_cistatic int qib_init_one(struct pci_dev *, const struct pci_device_id *); 11618c2ecf20Sopenharmony_cistatic void qib_shutdown_one(struct pci_dev *); 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci#define DRIVER_LOAD_MSG "Intel " QIB_DRV_NAME " loaded: " 11648c2ecf20Sopenharmony_ci#define PFX QIB_DRV_NAME ": " 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_cistatic const struct pci_device_id qib_pci_tbl[] = { 11678c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_QLOGIC_IB_6120) }, 11688c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_IB_7220) }, 11698c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_IB_7322) }, 11708c2ecf20Sopenharmony_ci { 0, } 11718c2ecf20Sopenharmony_ci}; 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, qib_pci_tbl); 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_cistatic struct pci_driver qib_driver = { 11768c2ecf20Sopenharmony_ci .name = QIB_DRV_NAME, 11778c2ecf20Sopenharmony_ci .probe = qib_init_one, 11788c2ecf20Sopenharmony_ci .remove = qib_remove_one, 11798c2ecf20Sopenharmony_ci .shutdown = qib_shutdown_one, 11808c2ecf20Sopenharmony_ci .id_table = qib_pci_tbl, 11818c2ecf20Sopenharmony_ci .err_handler = &qib_pci_err_handler, 11828c2ecf20Sopenharmony_ci}; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci#ifdef CONFIG_INFINIBAND_QIB_DCA 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_cistatic int qib_notify_dca(struct notifier_block *, unsigned long, void *); 11878c2ecf20Sopenharmony_cistatic struct notifier_block dca_notifier = { 11888c2ecf20Sopenharmony_ci .notifier_call = qib_notify_dca, 11898c2ecf20Sopenharmony_ci .next = NULL, 11908c2ecf20Sopenharmony_ci .priority = 0 11918c2ecf20Sopenharmony_ci}; 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_cistatic int qib_notify_dca_device(struct device *device, void *data) 11948c2ecf20Sopenharmony_ci{ 11958c2ecf20Sopenharmony_ci struct qib_devdata *dd = dev_get_drvdata(device); 11968c2ecf20Sopenharmony_ci unsigned long event = *(unsigned long *)data; 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci return dd->f_notify_dca(dd, event); 11998c2ecf20Sopenharmony_ci} 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_cistatic int qib_notify_dca(struct notifier_block *nb, unsigned long event, 12028c2ecf20Sopenharmony_ci void *p) 12038c2ecf20Sopenharmony_ci{ 12048c2ecf20Sopenharmony_ci int rval; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci rval = driver_for_each_device(&qib_driver.driver, NULL, 12078c2ecf20Sopenharmony_ci &event, qib_notify_dca_device); 12088c2ecf20Sopenharmony_ci return rval ? NOTIFY_BAD : NOTIFY_DONE; 12098c2ecf20Sopenharmony_ci} 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci#endif 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci/* 12148c2ecf20Sopenharmony_ci * Do all the generic driver unit- and chip-independent memory 12158c2ecf20Sopenharmony_ci * allocation and initialization. 12168c2ecf20Sopenharmony_ci */ 12178c2ecf20Sopenharmony_cistatic int __init qib_ib_init(void) 12188c2ecf20Sopenharmony_ci{ 12198c2ecf20Sopenharmony_ci int ret; 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci ret = qib_dev_init(); 12228c2ecf20Sopenharmony_ci if (ret) 12238c2ecf20Sopenharmony_ci goto bail; 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci /* 12268c2ecf20Sopenharmony_ci * These must be called before the driver is registered with 12278c2ecf20Sopenharmony_ci * the PCI subsystem. 12288c2ecf20Sopenharmony_ci */ 12298c2ecf20Sopenharmony_ci#ifdef CONFIG_INFINIBAND_QIB_DCA 12308c2ecf20Sopenharmony_ci dca_register_notify(&dca_notifier); 12318c2ecf20Sopenharmony_ci#endif 12328c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 12338c2ecf20Sopenharmony_ci qib_dbg_init(); 12348c2ecf20Sopenharmony_ci#endif 12358c2ecf20Sopenharmony_ci ret = pci_register_driver(&qib_driver); 12368c2ecf20Sopenharmony_ci if (ret < 0) { 12378c2ecf20Sopenharmony_ci pr_err("Unable to register driver: error %d\n", -ret); 12388c2ecf20Sopenharmony_ci goto bail_dev; 12398c2ecf20Sopenharmony_ci } 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci /* not fatal if it doesn't work */ 12428c2ecf20Sopenharmony_ci if (qib_init_qibfs()) 12438c2ecf20Sopenharmony_ci pr_err("Unable to register ipathfs\n"); 12448c2ecf20Sopenharmony_ci goto bail; /* all OK */ 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_cibail_dev: 12478c2ecf20Sopenharmony_ci#ifdef CONFIG_INFINIBAND_QIB_DCA 12488c2ecf20Sopenharmony_ci dca_unregister_notify(&dca_notifier); 12498c2ecf20Sopenharmony_ci#endif 12508c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 12518c2ecf20Sopenharmony_ci qib_dbg_exit(); 12528c2ecf20Sopenharmony_ci#endif 12538c2ecf20Sopenharmony_ci qib_dev_cleanup(); 12548c2ecf20Sopenharmony_cibail: 12558c2ecf20Sopenharmony_ci return ret; 12568c2ecf20Sopenharmony_ci} 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_cimodule_init(qib_ib_init); 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_ci/* 12618c2ecf20Sopenharmony_ci * Do the non-unit driver cleanup, memory free, etc. at unload. 12628c2ecf20Sopenharmony_ci */ 12638c2ecf20Sopenharmony_cistatic void __exit qib_ib_cleanup(void) 12648c2ecf20Sopenharmony_ci{ 12658c2ecf20Sopenharmony_ci int ret; 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci ret = qib_exit_qibfs(); 12688c2ecf20Sopenharmony_ci if (ret) 12698c2ecf20Sopenharmony_ci pr_err( 12708c2ecf20Sopenharmony_ci "Unable to cleanup counter filesystem: error %d\n", 12718c2ecf20Sopenharmony_ci -ret); 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci#ifdef CONFIG_INFINIBAND_QIB_DCA 12748c2ecf20Sopenharmony_ci dca_unregister_notify(&dca_notifier); 12758c2ecf20Sopenharmony_ci#endif 12768c2ecf20Sopenharmony_ci pci_unregister_driver(&qib_driver); 12778c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 12788c2ecf20Sopenharmony_ci qib_dbg_exit(); 12798c2ecf20Sopenharmony_ci#endif 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci qib_cpulist_count = 0; 12828c2ecf20Sopenharmony_ci kfree(qib_cpulist); 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci WARN_ON(!xa_empty(&qib_dev_table)); 12858c2ecf20Sopenharmony_ci qib_dev_cleanup(); 12868c2ecf20Sopenharmony_ci} 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_cimodule_exit(qib_ib_cleanup); 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci/* this can only be called after a successful initialization */ 12918c2ecf20Sopenharmony_cistatic void cleanup_device_data(struct qib_devdata *dd) 12928c2ecf20Sopenharmony_ci{ 12938c2ecf20Sopenharmony_ci int ctxt; 12948c2ecf20Sopenharmony_ci int pidx; 12958c2ecf20Sopenharmony_ci struct qib_ctxtdata **tmp; 12968c2ecf20Sopenharmony_ci unsigned long flags; 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci /* users can't do anything more with chip */ 12998c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) { 13008c2ecf20Sopenharmony_ci if (dd->pport[pidx].statusp) 13018c2ecf20Sopenharmony_ci *dd->pport[pidx].statusp &= ~QIB_STATUS_CHIP_PRESENT; 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci spin_lock(&dd->pport[pidx].cc_shadow_lock); 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci kfree(dd->pport[pidx].congestion_entries); 13068c2ecf20Sopenharmony_ci dd->pport[pidx].congestion_entries = NULL; 13078c2ecf20Sopenharmony_ci kfree(dd->pport[pidx].ccti_entries); 13088c2ecf20Sopenharmony_ci dd->pport[pidx].ccti_entries = NULL; 13098c2ecf20Sopenharmony_ci kfree(dd->pport[pidx].ccti_entries_shadow); 13108c2ecf20Sopenharmony_ci dd->pport[pidx].ccti_entries_shadow = NULL; 13118c2ecf20Sopenharmony_ci kfree(dd->pport[pidx].congestion_entries_shadow); 13128c2ecf20Sopenharmony_ci dd->pport[pidx].congestion_entries_shadow = NULL; 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci spin_unlock(&dd->pport[pidx].cc_shadow_lock); 13158c2ecf20Sopenharmony_ci } 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci qib_disable_wc(dd); 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_ci if (dd->pioavailregs_dma) { 13208c2ecf20Sopenharmony_ci dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE, 13218c2ecf20Sopenharmony_ci (void *) dd->pioavailregs_dma, 13228c2ecf20Sopenharmony_ci dd->pioavailregs_phys); 13238c2ecf20Sopenharmony_ci dd->pioavailregs_dma = NULL; 13248c2ecf20Sopenharmony_ci } 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci if (dd->pageshadow) { 13278c2ecf20Sopenharmony_ci struct page **tmpp = dd->pageshadow; 13288c2ecf20Sopenharmony_ci dma_addr_t *tmpd = dd->physshadow; 13298c2ecf20Sopenharmony_ci int i; 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci for (ctxt = 0; ctxt < dd->cfgctxts; ctxt++) { 13328c2ecf20Sopenharmony_ci int ctxt_tidbase = ctxt * dd->rcvtidcnt; 13338c2ecf20Sopenharmony_ci int maxtid = ctxt_tidbase + dd->rcvtidcnt; 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci for (i = ctxt_tidbase; i < maxtid; i++) { 13368c2ecf20Sopenharmony_ci if (!tmpp[i]) 13378c2ecf20Sopenharmony_ci continue; 13388c2ecf20Sopenharmony_ci pci_unmap_page(dd->pcidev, tmpd[i], 13398c2ecf20Sopenharmony_ci PAGE_SIZE, PCI_DMA_FROMDEVICE); 13408c2ecf20Sopenharmony_ci qib_release_user_pages(&tmpp[i], 1); 13418c2ecf20Sopenharmony_ci tmpp[i] = NULL; 13428c2ecf20Sopenharmony_ci } 13438c2ecf20Sopenharmony_ci } 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci dd->pageshadow = NULL; 13468c2ecf20Sopenharmony_ci vfree(tmpp); 13478c2ecf20Sopenharmony_ci dd->physshadow = NULL; 13488c2ecf20Sopenharmony_ci vfree(tmpd); 13498c2ecf20Sopenharmony_ci } 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci /* 13528c2ecf20Sopenharmony_ci * Free any resources still in use (usually just kernel contexts) 13538c2ecf20Sopenharmony_ci * at unload; we do for ctxtcnt, because that's what we allocate. 13548c2ecf20Sopenharmony_ci * We acquire lock to be really paranoid that rcd isn't being 13558c2ecf20Sopenharmony_ci * accessed from some interrupt-related code (that should not happen, 13568c2ecf20Sopenharmony_ci * but best to be sure). 13578c2ecf20Sopenharmony_ci */ 13588c2ecf20Sopenharmony_ci spin_lock_irqsave(&dd->uctxt_lock, flags); 13598c2ecf20Sopenharmony_ci tmp = dd->rcd; 13608c2ecf20Sopenharmony_ci dd->rcd = NULL; 13618c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dd->uctxt_lock, flags); 13628c2ecf20Sopenharmony_ci for (ctxt = 0; tmp && ctxt < dd->ctxtcnt; ctxt++) { 13638c2ecf20Sopenharmony_ci struct qib_ctxtdata *rcd = tmp[ctxt]; 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci tmp[ctxt] = NULL; /* debugging paranoia */ 13668c2ecf20Sopenharmony_ci qib_free_ctxtdata(dd, rcd); 13678c2ecf20Sopenharmony_ci } 13688c2ecf20Sopenharmony_ci kfree(tmp); 13698c2ecf20Sopenharmony_ci} 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci/* 13728c2ecf20Sopenharmony_ci * Clean up on unit shutdown, or error during unit load after 13738c2ecf20Sopenharmony_ci * successful initialization. 13748c2ecf20Sopenharmony_ci */ 13758c2ecf20Sopenharmony_cistatic void qib_postinit_cleanup(struct qib_devdata *dd) 13768c2ecf20Sopenharmony_ci{ 13778c2ecf20Sopenharmony_ci /* 13788c2ecf20Sopenharmony_ci * Clean up chip-specific stuff. 13798c2ecf20Sopenharmony_ci * We check for NULL here, because it's outside 13808c2ecf20Sopenharmony_ci * the kregbase check, and we need to call it 13818c2ecf20Sopenharmony_ci * after the free_irq. Thus it's possible that 13828c2ecf20Sopenharmony_ci * the function pointers were never initialized. 13838c2ecf20Sopenharmony_ci */ 13848c2ecf20Sopenharmony_ci if (dd->f_cleanup) 13858c2ecf20Sopenharmony_ci dd->f_cleanup(dd); 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_ci qib_pcie_ddcleanup(dd); 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci cleanup_device_data(dd); 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci qib_free_devdata(dd); 13928c2ecf20Sopenharmony_ci} 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_cistatic int qib_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 13958c2ecf20Sopenharmony_ci{ 13968c2ecf20Sopenharmony_ci int ret, j, pidx, initfail; 13978c2ecf20Sopenharmony_ci struct qib_devdata *dd = NULL; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci ret = qib_pcie_init(pdev, ent); 14008c2ecf20Sopenharmony_ci if (ret) 14018c2ecf20Sopenharmony_ci goto bail; 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci /* 14048c2ecf20Sopenharmony_ci * Do device-specific initialiation, function table setup, dd 14058c2ecf20Sopenharmony_ci * allocation, etc. 14068c2ecf20Sopenharmony_ci */ 14078c2ecf20Sopenharmony_ci switch (ent->device) { 14088c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_IB_6120: 14098c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_MSI 14108c2ecf20Sopenharmony_ci dd = qib_init_iba6120_funcs(pdev, ent); 14118c2ecf20Sopenharmony_ci#else 14128c2ecf20Sopenharmony_ci qib_early_err(&pdev->dev, 14138c2ecf20Sopenharmony_ci "Intel PCIE device 0x%x cannot work if CONFIG_PCI_MSI is not enabled\n", 14148c2ecf20Sopenharmony_ci ent->device); 14158c2ecf20Sopenharmony_ci dd = ERR_PTR(-ENODEV); 14168c2ecf20Sopenharmony_ci#endif 14178c2ecf20Sopenharmony_ci break; 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_IB_7220: 14208c2ecf20Sopenharmony_ci dd = qib_init_iba7220_funcs(pdev, ent); 14218c2ecf20Sopenharmony_ci break; 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_IB_7322: 14248c2ecf20Sopenharmony_ci dd = qib_init_iba7322_funcs(pdev, ent); 14258c2ecf20Sopenharmony_ci break; 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci default: 14288c2ecf20Sopenharmony_ci qib_early_err(&pdev->dev, 14298c2ecf20Sopenharmony_ci "Failing on unknown Intel deviceid 0x%x\n", 14308c2ecf20Sopenharmony_ci ent->device); 14318c2ecf20Sopenharmony_ci ret = -ENODEV; 14328c2ecf20Sopenharmony_ci } 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci if (IS_ERR(dd)) 14358c2ecf20Sopenharmony_ci ret = PTR_ERR(dd); 14368c2ecf20Sopenharmony_ci if (ret) 14378c2ecf20Sopenharmony_ci goto bail; /* error already printed */ 14388c2ecf20Sopenharmony_ci 14398c2ecf20Sopenharmony_ci ret = qib_create_workqueues(dd); 14408c2ecf20Sopenharmony_ci if (ret) 14418c2ecf20Sopenharmony_ci goto bail; 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci /* do the generic initialization */ 14448c2ecf20Sopenharmony_ci initfail = qib_init(dd, 0); 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_ci ret = qib_register_ib_device(dd); 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci /* 14498c2ecf20Sopenharmony_ci * Now ready for use. this should be cleared whenever we 14508c2ecf20Sopenharmony_ci * detect a reset, or initiate one. If earlier failure, 14518c2ecf20Sopenharmony_ci * we still create devices, so diags, etc. can be used 14528c2ecf20Sopenharmony_ci * to determine cause of problem. 14538c2ecf20Sopenharmony_ci */ 14548c2ecf20Sopenharmony_ci if (!qib_mini_init && !initfail && !ret) 14558c2ecf20Sopenharmony_ci dd->flags |= QIB_INITTED; 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci j = qib_device_create(dd); 14588c2ecf20Sopenharmony_ci if (j) 14598c2ecf20Sopenharmony_ci qib_dev_err(dd, "Failed to create /dev devices: %d\n", -j); 14608c2ecf20Sopenharmony_ci j = qibfs_add(dd); 14618c2ecf20Sopenharmony_ci if (j) 14628c2ecf20Sopenharmony_ci qib_dev_err(dd, "Failed filesystem setup for counters: %d\n", 14638c2ecf20Sopenharmony_ci -j); 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_ci if (qib_mini_init || initfail || ret) { 14668c2ecf20Sopenharmony_ci qib_stop_timers(dd); 14678c2ecf20Sopenharmony_ci flush_workqueue(ib_wq); 14688c2ecf20Sopenharmony_ci for (pidx = 0; pidx < dd->num_pports; ++pidx) 14698c2ecf20Sopenharmony_ci dd->f_quiet_serdes(dd->pport + pidx); 14708c2ecf20Sopenharmony_ci if (qib_mini_init) 14718c2ecf20Sopenharmony_ci goto bail; 14728c2ecf20Sopenharmony_ci if (!j) { 14738c2ecf20Sopenharmony_ci (void) qibfs_remove(dd); 14748c2ecf20Sopenharmony_ci qib_device_remove(dd); 14758c2ecf20Sopenharmony_ci } 14768c2ecf20Sopenharmony_ci if (!ret) 14778c2ecf20Sopenharmony_ci qib_unregister_ib_device(dd); 14788c2ecf20Sopenharmony_ci qib_postinit_cleanup(dd); 14798c2ecf20Sopenharmony_ci if (initfail) 14808c2ecf20Sopenharmony_ci ret = initfail; 14818c2ecf20Sopenharmony_ci goto bail; 14828c2ecf20Sopenharmony_ci } 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci ret = qib_enable_wc(dd); 14858c2ecf20Sopenharmony_ci if (ret) { 14868c2ecf20Sopenharmony_ci qib_dev_err(dd, 14878c2ecf20Sopenharmony_ci "Write combining not enabled (err %d): performance may be poor\n", 14888c2ecf20Sopenharmony_ci -ret); 14898c2ecf20Sopenharmony_ci ret = 0; 14908c2ecf20Sopenharmony_ci } 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci qib_verify_pioperf(dd); 14938c2ecf20Sopenharmony_cibail: 14948c2ecf20Sopenharmony_ci return ret; 14958c2ecf20Sopenharmony_ci} 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_cistatic void qib_remove_one(struct pci_dev *pdev) 14988c2ecf20Sopenharmony_ci{ 14998c2ecf20Sopenharmony_ci struct qib_devdata *dd = pci_get_drvdata(pdev); 15008c2ecf20Sopenharmony_ci int ret; 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci /* unregister from IB core */ 15038c2ecf20Sopenharmony_ci qib_unregister_ib_device(dd); 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci /* 15068c2ecf20Sopenharmony_ci * Disable the IB link, disable interrupts on the device, 15078c2ecf20Sopenharmony_ci * clear dma engines, etc. 15088c2ecf20Sopenharmony_ci */ 15098c2ecf20Sopenharmony_ci if (!qib_mini_init) 15108c2ecf20Sopenharmony_ci qib_shutdown_device(dd); 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci qib_stop_timers(dd); 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci /* wait until all of our (qsfp) queue_work() calls complete */ 15158c2ecf20Sopenharmony_ci flush_workqueue(ib_wq); 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci ret = qibfs_remove(dd); 15188c2ecf20Sopenharmony_ci if (ret) 15198c2ecf20Sopenharmony_ci qib_dev_err(dd, "Failed counters filesystem cleanup: %d\n", 15208c2ecf20Sopenharmony_ci -ret); 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci qib_device_remove(dd); 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci qib_postinit_cleanup(dd); 15258c2ecf20Sopenharmony_ci} 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_cistatic void qib_shutdown_one(struct pci_dev *pdev) 15288c2ecf20Sopenharmony_ci{ 15298c2ecf20Sopenharmony_ci struct qib_devdata *dd = pci_get_drvdata(pdev); 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci qib_shutdown_device(dd); 15328c2ecf20Sopenharmony_ci} 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci/** 15358c2ecf20Sopenharmony_ci * qib_create_rcvhdrq - create a receive header queue 15368c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 15378c2ecf20Sopenharmony_ci * @rcd: the context data 15388c2ecf20Sopenharmony_ci * 15398c2ecf20Sopenharmony_ci * This must be contiguous memory (from an i/o perspective), and must be 15408c2ecf20Sopenharmony_ci * DMA'able (which means for some systems, it will go through an IOMMU, 15418c2ecf20Sopenharmony_ci * or be forced into a low address range). 15428c2ecf20Sopenharmony_ci */ 15438c2ecf20Sopenharmony_ciint qib_create_rcvhdrq(struct qib_devdata *dd, struct qib_ctxtdata *rcd) 15448c2ecf20Sopenharmony_ci{ 15458c2ecf20Sopenharmony_ci unsigned amt; 15468c2ecf20Sopenharmony_ci int old_node_id; 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci if (!rcd->rcvhdrq) { 15498c2ecf20Sopenharmony_ci dma_addr_t phys_hdrqtail; 15508c2ecf20Sopenharmony_ci gfp_t gfp_flags; 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci amt = ALIGN(dd->rcvhdrcnt * dd->rcvhdrentsize * 15538c2ecf20Sopenharmony_ci sizeof(u32), PAGE_SIZE); 15548c2ecf20Sopenharmony_ci gfp_flags = (rcd->ctxt >= dd->first_user_ctxt) ? 15558c2ecf20Sopenharmony_ci GFP_USER : GFP_KERNEL; 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci old_node_id = dev_to_node(&dd->pcidev->dev); 15588c2ecf20Sopenharmony_ci set_dev_node(&dd->pcidev->dev, rcd->node_id); 15598c2ecf20Sopenharmony_ci rcd->rcvhdrq = dma_alloc_coherent( 15608c2ecf20Sopenharmony_ci &dd->pcidev->dev, amt, &rcd->rcvhdrq_phys, 15618c2ecf20Sopenharmony_ci gfp_flags | __GFP_COMP); 15628c2ecf20Sopenharmony_ci set_dev_node(&dd->pcidev->dev, old_node_id); 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci if (!rcd->rcvhdrq) { 15658c2ecf20Sopenharmony_ci qib_dev_err(dd, 15668c2ecf20Sopenharmony_ci "attempt to allocate %d bytes for ctxt %u rcvhdrq failed\n", 15678c2ecf20Sopenharmony_ci amt, rcd->ctxt); 15688c2ecf20Sopenharmony_ci goto bail; 15698c2ecf20Sopenharmony_ci } 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_ci if (rcd->ctxt >= dd->first_user_ctxt) { 15728c2ecf20Sopenharmony_ci rcd->user_event_mask = vmalloc_user(PAGE_SIZE); 15738c2ecf20Sopenharmony_ci if (!rcd->user_event_mask) 15748c2ecf20Sopenharmony_ci goto bail_free_hdrq; 15758c2ecf20Sopenharmony_ci } 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci if (!(dd->flags & QIB_NODMA_RTAIL)) { 15788c2ecf20Sopenharmony_ci set_dev_node(&dd->pcidev->dev, rcd->node_id); 15798c2ecf20Sopenharmony_ci rcd->rcvhdrtail_kvaddr = dma_alloc_coherent( 15808c2ecf20Sopenharmony_ci &dd->pcidev->dev, PAGE_SIZE, &phys_hdrqtail, 15818c2ecf20Sopenharmony_ci gfp_flags); 15828c2ecf20Sopenharmony_ci set_dev_node(&dd->pcidev->dev, old_node_id); 15838c2ecf20Sopenharmony_ci if (!rcd->rcvhdrtail_kvaddr) 15848c2ecf20Sopenharmony_ci goto bail_free; 15858c2ecf20Sopenharmony_ci rcd->rcvhdrqtailaddr_phys = phys_hdrqtail; 15868c2ecf20Sopenharmony_ci } 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci rcd->rcvhdrq_size = amt; 15898c2ecf20Sopenharmony_ci } 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_ci /* clear for security and sanity on each use */ 15928c2ecf20Sopenharmony_ci memset(rcd->rcvhdrq, 0, rcd->rcvhdrq_size); 15938c2ecf20Sopenharmony_ci if (rcd->rcvhdrtail_kvaddr) 15948c2ecf20Sopenharmony_ci memset(rcd->rcvhdrtail_kvaddr, 0, PAGE_SIZE); 15958c2ecf20Sopenharmony_ci return 0; 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_cibail_free: 15988c2ecf20Sopenharmony_ci qib_dev_err(dd, 15998c2ecf20Sopenharmony_ci "attempt to allocate 1 page for ctxt %u rcvhdrqtailaddr failed\n", 16008c2ecf20Sopenharmony_ci rcd->ctxt); 16018c2ecf20Sopenharmony_ci vfree(rcd->user_event_mask); 16028c2ecf20Sopenharmony_ci rcd->user_event_mask = NULL; 16038c2ecf20Sopenharmony_cibail_free_hdrq: 16048c2ecf20Sopenharmony_ci dma_free_coherent(&dd->pcidev->dev, amt, rcd->rcvhdrq, 16058c2ecf20Sopenharmony_ci rcd->rcvhdrq_phys); 16068c2ecf20Sopenharmony_ci rcd->rcvhdrq = NULL; 16078c2ecf20Sopenharmony_cibail: 16088c2ecf20Sopenharmony_ci return -ENOMEM; 16098c2ecf20Sopenharmony_ci} 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_ci/** 16128c2ecf20Sopenharmony_ci * allocate eager buffers, both kernel and user contexts. 16138c2ecf20Sopenharmony_ci * @rcd: the context we are setting up. 16148c2ecf20Sopenharmony_ci * 16158c2ecf20Sopenharmony_ci * Allocate the eager TID buffers and program them into hip. 16168c2ecf20Sopenharmony_ci * They are no longer completely contiguous, we do multiple allocation 16178c2ecf20Sopenharmony_ci * calls. Otherwise we get the OOM code involved, by asking for too 16188c2ecf20Sopenharmony_ci * much per call, with disastrous results on some kernels. 16198c2ecf20Sopenharmony_ci */ 16208c2ecf20Sopenharmony_ciint qib_setup_eagerbufs(struct qib_ctxtdata *rcd) 16218c2ecf20Sopenharmony_ci{ 16228c2ecf20Sopenharmony_ci struct qib_devdata *dd = rcd->dd; 16238c2ecf20Sopenharmony_ci unsigned e, egrcnt, egrperchunk, chunk, egrsize, egroff; 16248c2ecf20Sopenharmony_ci size_t size; 16258c2ecf20Sopenharmony_ci gfp_t gfp_flags; 16268c2ecf20Sopenharmony_ci int old_node_id; 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci /* 16298c2ecf20Sopenharmony_ci * GFP_USER, but without GFP_FS, so buffer cache can be 16308c2ecf20Sopenharmony_ci * coalesced (we hope); otherwise, even at order 4, 16318c2ecf20Sopenharmony_ci * heavy filesystem activity makes these fail, and we can 16328c2ecf20Sopenharmony_ci * use compound pages. 16338c2ecf20Sopenharmony_ci */ 16348c2ecf20Sopenharmony_ci gfp_flags = __GFP_RECLAIM | __GFP_IO | __GFP_COMP; 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci egrcnt = rcd->rcvegrcnt; 16378c2ecf20Sopenharmony_ci egroff = rcd->rcvegr_tid_base; 16388c2ecf20Sopenharmony_ci egrsize = dd->rcvegrbufsize; 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_ci chunk = rcd->rcvegrbuf_chunks; 16418c2ecf20Sopenharmony_ci egrperchunk = rcd->rcvegrbufs_perchunk; 16428c2ecf20Sopenharmony_ci size = rcd->rcvegrbuf_size; 16438c2ecf20Sopenharmony_ci if (!rcd->rcvegrbuf) { 16448c2ecf20Sopenharmony_ci rcd->rcvegrbuf = 16458c2ecf20Sopenharmony_ci kcalloc_node(chunk, sizeof(rcd->rcvegrbuf[0]), 16468c2ecf20Sopenharmony_ci GFP_KERNEL, rcd->node_id); 16478c2ecf20Sopenharmony_ci if (!rcd->rcvegrbuf) 16488c2ecf20Sopenharmony_ci goto bail; 16498c2ecf20Sopenharmony_ci } 16508c2ecf20Sopenharmony_ci if (!rcd->rcvegrbuf_phys) { 16518c2ecf20Sopenharmony_ci rcd->rcvegrbuf_phys = 16528c2ecf20Sopenharmony_ci kmalloc_array_node(chunk, 16538c2ecf20Sopenharmony_ci sizeof(rcd->rcvegrbuf_phys[0]), 16548c2ecf20Sopenharmony_ci GFP_KERNEL, rcd->node_id); 16558c2ecf20Sopenharmony_ci if (!rcd->rcvegrbuf_phys) 16568c2ecf20Sopenharmony_ci goto bail_rcvegrbuf; 16578c2ecf20Sopenharmony_ci } 16588c2ecf20Sopenharmony_ci for (e = 0; e < rcd->rcvegrbuf_chunks; e++) { 16598c2ecf20Sopenharmony_ci if (rcd->rcvegrbuf[e]) 16608c2ecf20Sopenharmony_ci continue; 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci old_node_id = dev_to_node(&dd->pcidev->dev); 16638c2ecf20Sopenharmony_ci set_dev_node(&dd->pcidev->dev, rcd->node_id); 16648c2ecf20Sopenharmony_ci rcd->rcvegrbuf[e] = 16658c2ecf20Sopenharmony_ci dma_alloc_coherent(&dd->pcidev->dev, size, 16668c2ecf20Sopenharmony_ci &rcd->rcvegrbuf_phys[e], 16678c2ecf20Sopenharmony_ci gfp_flags); 16688c2ecf20Sopenharmony_ci set_dev_node(&dd->pcidev->dev, old_node_id); 16698c2ecf20Sopenharmony_ci if (!rcd->rcvegrbuf[e]) 16708c2ecf20Sopenharmony_ci goto bail_rcvegrbuf_phys; 16718c2ecf20Sopenharmony_ci } 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_ci rcd->rcvegr_phys = rcd->rcvegrbuf_phys[0]; 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci for (e = chunk = 0; chunk < rcd->rcvegrbuf_chunks; chunk++) { 16768c2ecf20Sopenharmony_ci dma_addr_t pa = rcd->rcvegrbuf_phys[chunk]; 16778c2ecf20Sopenharmony_ci unsigned i; 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci /* clear for security and sanity on each use */ 16808c2ecf20Sopenharmony_ci memset(rcd->rcvegrbuf[chunk], 0, size); 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci for (i = 0; e < egrcnt && i < egrperchunk; e++, i++) { 16838c2ecf20Sopenharmony_ci dd->f_put_tid(dd, e + egroff + 16848c2ecf20Sopenharmony_ci (u64 __iomem *) 16858c2ecf20Sopenharmony_ci ((char __iomem *) 16868c2ecf20Sopenharmony_ci dd->kregbase + 16878c2ecf20Sopenharmony_ci dd->rcvegrbase), 16888c2ecf20Sopenharmony_ci RCVHQ_RCV_TYPE_EAGER, pa); 16898c2ecf20Sopenharmony_ci pa += egrsize; 16908c2ecf20Sopenharmony_ci } 16918c2ecf20Sopenharmony_ci cond_resched(); /* don't hog the cpu */ 16928c2ecf20Sopenharmony_ci } 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci return 0; 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_cibail_rcvegrbuf_phys: 16978c2ecf20Sopenharmony_ci for (e = 0; e < rcd->rcvegrbuf_chunks && rcd->rcvegrbuf[e]; e++) 16988c2ecf20Sopenharmony_ci dma_free_coherent(&dd->pcidev->dev, size, 16998c2ecf20Sopenharmony_ci rcd->rcvegrbuf[e], rcd->rcvegrbuf_phys[e]); 17008c2ecf20Sopenharmony_ci kfree(rcd->rcvegrbuf_phys); 17018c2ecf20Sopenharmony_ci rcd->rcvegrbuf_phys = NULL; 17028c2ecf20Sopenharmony_cibail_rcvegrbuf: 17038c2ecf20Sopenharmony_ci kfree(rcd->rcvegrbuf); 17048c2ecf20Sopenharmony_ci rcd->rcvegrbuf = NULL; 17058c2ecf20Sopenharmony_cibail: 17068c2ecf20Sopenharmony_ci return -ENOMEM; 17078c2ecf20Sopenharmony_ci} 17088c2ecf20Sopenharmony_ci 17098c2ecf20Sopenharmony_ci/* 17108c2ecf20Sopenharmony_ci * Note: Changes to this routine should be mirrored 17118c2ecf20Sopenharmony_ci * for the diagnostics routine qib_remap_ioaddr32(). 17128c2ecf20Sopenharmony_ci * There is also related code for VL15 buffers in qib_init_7322_variables(). 17138c2ecf20Sopenharmony_ci * The teardown code that unmaps is in qib_pcie_ddcleanup() 17148c2ecf20Sopenharmony_ci */ 17158c2ecf20Sopenharmony_ciint init_chip_wc_pat(struct qib_devdata *dd, u32 vl15buflen) 17168c2ecf20Sopenharmony_ci{ 17178c2ecf20Sopenharmony_ci u64 __iomem *qib_kregbase = NULL; 17188c2ecf20Sopenharmony_ci void __iomem *qib_piobase = NULL; 17198c2ecf20Sopenharmony_ci u64 __iomem *qib_userbase = NULL; 17208c2ecf20Sopenharmony_ci u64 qib_kreglen; 17218c2ecf20Sopenharmony_ci u64 qib_pio2koffset = dd->piobufbase & 0xffffffff; 17228c2ecf20Sopenharmony_ci u64 qib_pio4koffset = dd->piobufbase >> 32; 17238c2ecf20Sopenharmony_ci u64 qib_pio2klen = dd->piobcnt2k * dd->palign; 17248c2ecf20Sopenharmony_ci u64 qib_pio4klen = dd->piobcnt4k * dd->align4k; 17258c2ecf20Sopenharmony_ci u64 qib_physaddr = dd->physaddr; 17268c2ecf20Sopenharmony_ci u64 qib_piolen; 17278c2ecf20Sopenharmony_ci u64 qib_userlen = 0; 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci /* 17308c2ecf20Sopenharmony_ci * Free the old mapping because the kernel will try to reuse the 17318c2ecf20Sopenharmony_ci * old mapping and not create a new mapping with the 17328c2ecf20Sopenharmony_ci * write combining attribute. 17338c2ecf20Sopenharmony_ci */ 17348c2ecf20Sopenharmony_ci iounmap(dd->kregbase); 17358c2ecf20Sopenharmony_ci dd->kregbase = NULL; 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_ci /* 17388c2ecf20Sopenharmony_ci * Assumes chip address space looks like: 17398c2ecf20Sopenharmony_ci * - kregs + sregs + cregs + uregs (in any order) 17408c2ecf20Sopenharmony_ci * - piobufs (2K and 4K bufs in either order) 17418c2ecf20Sopenharmony_ci * or: 17428c2ecf20Sopenharmony_ci * - kregs + sregs + cregs (in any order) 17438c2ecf20Sopenharmony_ci * - piobufs (2K and 4K bufs in either order) 17448c2ecf20Sopenharmony_ci * - uregs 17458c2ecf20Sopenharmony_ci */ 17468c2ecf20Sopenharmony_ci if (dd->piobcnt4k == 0) { 17478c2ecf20Sopenharmony_ci qib_kreglen = qib_pio2koffset; 17488c2ecf20Sopenharmony_ci qib_piolen = qib_pio2klen; 17498c2ecf20Sopenharmony_ci } else if (qib_pio2koffset < qib_pio4koffset) { 17508c2ecf20Sopenharmony_ci qib_kreglen = qib_pio2koffset; 17518c2ecf20Sopenharmony_ci qib_piolen = qib_pio4koffset + qib_pio4klen - qib_kreglen; 17528c2ecf20Sopenharmony_ci } else { 17538c2ecf20Sopenharmony_ci qib_kreglen = qib_pio4koffset; 17548c2ecf20Sopenharmony_ci qib_piolen = qib_pio2koffset + qib_pio2klen - qib_kreglen; 17558c2ecf20Sopenharmony_ci } 17568c2ecf20Sopenharmony_ci qib_piolen += vl15buflen; 17578c2ecf20Sopenharmony_ci /* Map just the configured ports (not all hw ports) */ 17588c2ecf20Sopenharmony_ci if (dd->uregbase > qib_kreglen) 17598c2ecf20Sopenharmony_ci qib_userlen = dd->ureg_align * dd->cfgctxts; 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci /* Sanity checks passed, now create the new mappings */ 17628c2ecf20Sopenharmony_ci qib_kregbase = ioremap(qib_physaddr, qib_kreglen); 17638c2ecf20Sopenharmony_ci if (!qib_kregbase) 17648c2ecf20Sopenharmony_ci goto bail; 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci qib_piobase = ioremap_wc(qib_physaddr + qib_kreglen, qib_piolen); 17678c2ecf20Sopenharmony_ci if (!qib_piobase) 17688c2ecf20Sopenharmony_ci goto bail_kregbase; 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci if (qib_userlen) { 17718c2ecf20Sopenharmony_ci qib_userbase = ioremap(qib_physaddr + dd->uregbase, 17728c2ecf20Sopenharmony_ci qib_userlen); 17738c2ecf20Sopenharmony_ci if (!qib_userbase) 17748c2ecf20Sopenharmony_ci goto bail_piobase; 17758c2ecf20Sopenharmony_ci } 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci dd->kregbase = qib_kregbase; 17788c2ecf20Sopenharmony_ci dd->kregend = (u64 __iomem *) 17798c2ecf20Sopenharmony_ci ((char __iomem *) qib_kregbase + qib_kreglen); 17808c2ecf20Sopenharmony_ci dd->piobase = qib_piobase; 17818c2ecf20Sopenharmony_ci dd->pio2kbase = (void __iomem *) 17828c2ecf20Sopenharmony_ci (((char __iomem *) dd->piobase) + 17838c2ecf20Sopenharmony_ci qib_pio2koffset - qib_kreglen); 17848c2ecf20Sopenharmony_ci if (dd->piobcnt4k) 17858c2ecf20Sopenharmony_ci dd->pio4kbase = (void __iomem *) 17868c2ecf20Sopenharmony_ci (((char __iomem *) dd->piobase) + 17878c2ecf20Sopenharmony_ci qib_pio4koffset - qib_kreglen); 17888c2ecf20Sopenharmony_ci if (qib_userlen) 17898c2ecf20Sopenharmony_ci /* ureg will now be accessed relative to dd->userbase */ 17908c2ecf20Sopenharmony_ci dd->userbase = qib_userbase; 17918c2ecf20Sopenharmony_ci return 0; 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_cibail_piobase: 17948c2ecf20Sopenharmony_ci iounmap(qib_piobase); 17958c2ecf20Sopenharmony_cibail_kregbase: 17968c2ecf20Sopenharmony_ci iounmap(qib_kregbase); 17978c2ecf20Sopenharmony_cibail: 17988c2ecf20Sopenharmony_ci return -ENOMEM; 17998c2ecf20Sopenharmony_ci} 1800