18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2009-2010 Chelsio, Inc. All rights reserved. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 58c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 68c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 78c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 88c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 118c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 128c2ecf20Sopenharmony_ci * conditions are met: 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 158c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 168c2ecf20Sopenharmony_ci * disclaimer. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 198c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 208c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 218c2ecf20Sopenharmony_ci * provided with the distribution. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 248c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 258c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 268c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 278c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 288c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 298c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 308c2ecf20Sopenharmony_ci * SOFTWARE. 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci#include <linux/module.h> 338c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 348c2ecf20Sopenharmony_ci#include <linux/device.h> 358c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 368c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 378c2ecf20Sopenharmony_ci#include <linux/delay.h> 388c2ecf20Sopenharmony_ci#include <linux/errno.h> 398c2ecf20Sopenharmony_ci#include <linux/list.h> 408c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 418c2ecf20Sopenharmony_ci#include <linux/ethtool.h> 428c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h> 438c2ecf20Sopenharmony_ci#include <linux/inetdevice.h> 448c2ecf20Sopenharmony_ci#include <linux/io.h> 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#include <asm/irq.h> 478c2ecf20Sopenharmony_ci#include <asm/byteorder.h> 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#include <rdma/iw_cm.h> 508c2ecf20Sopenharmony_ci#include <rdma/ib_verbs.h> 518c2ecf20Sopenharmony_ci#include <rdma/ib_smi.h> 528c2ecf20Sopenharmony_ci#include <rdma/ib_umem.h> 538c2ecf20Sopenharmony_ci#include <rdma/ib_user_verbs.h> 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#include "iw_cxgb4.h" 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic int fastreg_support = 1; 588c2ecf20Sopenharmony_cimodule_param(fastreg_support, int, 0644); 598c2ecf20Sopenharmony_ciMODULE_PARM_DESC(fastreg_support, "Advertise fastreg support (default=1)"); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic void c4iw_dealloc_ucontext(struct ib_ucontext *context) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci struct c4iw_ucontext *ucontext = to_c4iw_ucontext(context); 648c2ecf20Sopenharmony_ci struct c4iw_dev *rhp; 658c2ecf20Sopenharmony_ci struct c4iw_mm_entry *mm, *tmp; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci pr_debug("context %p\n", context); 688c2ecf20Sopenharmony_ci rhp = to_c4iw_dev(ucontext->ibucontext.device); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci list_for_each_entry_safe(mm, tmp, &ucontext->mmaps, entry) 718c2ecf20Sopenharmony_ci kfree(mm); 728c2ecf20Sopenharmony_ci c4iw_release_dev_ucontext(&rhp->rdev, &ucontext->uctx); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic int c4iw_alloc_ucontext(struct ib_ucontext *ucontext, 768c2ecf20Sopenharmony_ci struct ib_udata *udata) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci struct ib_device *ibdev = ucontext->device; 798c2ecf20Sopenharmony_ci struct c4iw_ucontext *context = to_c4iw_ucontext(ucontext); 808c2ecf20Sopenharmony_ci struct c4iw_dev *rhp = to_c4iw_dev(ibdev); 818c2ecf20Sopenharmony_ci struct c4iw_alloc_ucontext_resp uresp; 828c2ecf20Sopenharmony_ci int ret = 0; 838c2ecf20Sopenharmony_ci struct c4iw_mm_entry *mm = NULL; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci pr_debug("ibdev %p\n", ibdev); 868c2ecf20Sopenharmony_ci c4iw_init_dev_ucontext(&rhp->rdev, &context->uctx); 878c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&context->mmaps); 888c2ecf20Sopenharmony_ci spin_lock_init(&context->mmap_lock); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (udata->outlen < sizeof(uresp) - sizeof(uresp.reserved)) { 918c2ecf20Sopenharmony_ci pr_err_once("Warning - downlevel libcxgb4 (non-fatal), device status page disabled\n"); 928c2ecf20Sopenharmony_ci rhp->rdev.flags |= T4_STATUS_PAGE_DISABLED; 938c2ecf20Sopenharmony_ci } else { 948c2ecf20Sopenharmony_ci mm = kmalloc(sizeof(*mm), GFP_KERNEL); 958c2ecf20Sopenharmony_ci if (!mm) { 968c2ecf20Sopenharmony_ci ret = -ENOMEM; 978c2ecf20Sopenharmony_ci goto err; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci uresp.status_page_size = PAGE_SIZE; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci spin_lock(&context->mmap_lock); 1038c2ecf20Sopenharmony_ci uresp.status_page_key = context->key; 1048c2ecf20Sopenharmony_ci context->key += PAGE_SIZE; 1058c2ecf20Sopenharmony_ci spin_unlock(&context->mmap_lock); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci ret = ib_copy_to_udata(udata, &uresp, 1088c2ecf20Sopenharmony_ci sizeof(uresp) - sizeof(uresp.reserved)); 1098c2ecf20Sopenharmony_ci if (ret) 1108c2ecf20Sopenharmony_ci goto err_mm; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci mm->key = uresp.status_page_key; 1138c2ecf20Sopenharmony_ci mm->addr = virt_to_phys(rhp->rdev.status_page); 1148c2ecf20Sopenharmony_ci mm->len = PAGE_SIZE; 1158c2ecf20Sopenharmony_ci insert_mmap(context, mm); 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci return 0; 1188c2ecf20Sopenharmony_cierr_mm: 1198c2ecf20Sopenharmony_ci kfree(mm); 1208c2ecf20Sopenharmony_cierr: 1218c2ecf20Sopenharmony_ci return ret; 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic int c4iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci int len = vma->vm_end - vma->vm_start; 1278c2ecf20Sopenharmony_ci u32 key = vma->vm_pgoff << PAGE_SHIFT; 1288c2ecf20Sopenharmony_ci struct c4iw_rdev *rdev; 1298c2ecf20Sopenharmony_ci int ret = 0; 1308c2ecf20Sopenharmony_ci struct c4iw_mm_entry *mm; 1318c2ecf20Sopenharmony_ci struct c4iw_ucontext *ucontext; 1328c2ecf20Sopenharmony_ci u64 addr; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci pr_debug("pgoff 0x%lx key 0x%x len %d\n", vma->vm_pgoff, 1358c2ecf20Sopenharmony_ci key, len); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci if (vma->vm_start & (PAGE_SIZE-1)) 1388c2ecf20Sopenharmony_ci return -EINVAL; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci rdev = &(to_c4iw_dev(context->device)->rdev); 1418c2ecf20Sopenharmony_ci ucontext = to_c4iw_ucontext(context); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci mm = remove_mmap(ucontext, key, len); 1448c2ecf20Sopenharmony_ci if (!mm) 1458c2ecf20Sopenharmony_ci return -EINVAL; 1468c2ecf20Sopenharmony_ci addr = mm->addr; 1478c2ecf20Sopenharmony_ci kfree(mm); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci if ((addr >= pci_resource_start(rdev->lldi.pdev, 0)) && 1508c2ecf20Sopenharmony_ci (addr < (pci_resource_start(rdev->lldi.pdev, 0) + 1518c2ecf20Sopenharmony_ci pci_resource_len(rdev->lldi.pdev, 0)))) { 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci /* 1548c2ecf20Sopenharmony_ci * MA_SYNC register... 1558c2ecf20Sopenharmony_ci */ 1568c2ecf20Sopenharmony_ci vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 1578c2ecf20Sopenharmony_ci ret = io_remap_pfn_range(vma, vma->vm_start, 1588c2ecf20Sopenharmony_ci addr >> PAGE_SHIFT, 1598c2ecf20Sopenharmony_ci len, vma->vm_page_prot); 1608c2ecf20Sopenharmony_ci } else if ((addr >= pci_resource_start(rdev->lldi.pdev, 2)) && 1618c2ecf20Sopenharmony_ci (addr < (pci_resource_start(rdev->lldi.pdev, 2) + 1628c2ecf20Sopenharmony_ci pci_resource_len(rdev->lldi.pdev, 2)))) { 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci /* 1658c2ecf20Sopenharmony_ci * Map user DB or OCQP memory... 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_ci if (addr >= rdev->oc_mw_pa) 1688c2ecf20Sopenharmony_ci vma->vm_page_prot = t4_pgprot_wc(vma->vm_page_prot); 1698c2ecf20Sopenharmony_ci else { 1708c2ecf20Sopenharmony_ci if (!is_t4(rdev->lldi.adapter_type)) 1718c2ecf20Sopenharmony_ci vma->vm_page_prot = 1728c2ecf20Sopenharmony_ci t4_pgprot_wc(vma->vm_page_prot); 1738c2ecf20Sopenharmony_ci else 1748c2ecf20Sopenharmony_ci vma->vm_page_prot = 1758c2ecf20Sopenharmony_ci pgprot_noncached(vma->vm_page_prot); 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci ret = io_remap_pfn_range(vma, vma->vm_start, 1788c2ecf20Sopenharmony_ci addr >> PAGE_SHIFT, 1798c2ecf20Sopenharmony_ci len, vma->vm_page_prot); 1808c2ecf20Sopenharmony_ci } else { 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci /* 1838c2ecf20Sopenharmony_ci * Map WQ or CQ contig dma memory... 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ci ret = remap_pfn_range(vma, vma->vm_start, 1868c2ecf20Sopenharmony_ci addr >> PAGE_SHIFT, 1878c2ecf20Sopenharmony_ci len, vma->vm_page_prot); 1888c2ecf20Sopenharmony_ci } 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci return ret; 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic int c4iw_deallocate_pd(struct ib_pd *pd, struct ib_udata *udata) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci struct c4iw_dev *rhp; 1968c2ecf20Sopenharmony_ci struct c4iw_pd *php; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci php = to_c4iw_pd(pd); 1998c2ecf20Sopenharmony_ci rhp = php->rhp; 2008c2ecf20Sopenharmony_ci pr_debug("ibpd %p pdid 0x%x\n", pd, php->pdid); 2018c2ecf20Sopenharmony_ci c4iw_put_resource(&rhp->rdev.resource.pdid_table, php->pdid); 2028c2ecf20Sopenharmony_ci mutex_lock(&rhp->rdev.stats.lock); 2038c2ecf20Sopenharmony_ci rhp->rdev.stats.pd.cur--; 2048c2ecf20Sopenharmony_ci mutex_unlock(&rhp->rdev.stats.lock); 2058c2ecf20Sopenharmony_ci return 0; 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic int c4iw_allocate_pd(struct ib_pd *pd, struct ib_udata *udata) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci struct c4iw_pd *php = to_c4iw_pd(pd); 2118c2ecf20Sopenharmony_ci struct ib_device *ibdev = pd->device; 2128c2ecf20Sopenharmony_ci u32 pdid; 2138c2ecf20Sopenharmony_ci struct c4iw_dev *rhp; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci pr_debug("ibdev %p\n", ibdev); 2168c2ecf20Sopenharmony_ci rhp = (struct c4iw_dev *) ibdev; 2178c2ecf20Sopenharmony_ci pdid = c4iw_get_resource(&rhp->rdev.resource.pdid_table); 2188c2ecf20Sopenharmony_ci if (!pdid) 2198c2ecf20Sopenharmony_ci return -EINVAL; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci php->pdid = pdid; 2228c2ecf20Sopenharmony_ci php->rhp = rhp; 2238c2ecf20Sopenharmony_ci if (udata) { 2248c2ecf20Sopenharmony_ci struct c4iw_alloc_pd_resp uresp = {.pdid = php->pdid}; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci if (ib_copy_to_udata(udata, &uresp, sizeof(uresp))) { 2278c2ecf20Sopenharmony_ci c4iw_deallocate_pd(&php->ibpd, udata); 2288c2ecf20Sopenharmony_ci return -EFAULT; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci mutex_lock(&rhp->rdev.stats.lock); 2328c2ecf20Sopenharmony_ci rhp->rdev.stats.pd.cur++; 2338c2ecf20Sopenharmony_ci if (rhp->rdev.stats.pd.cur > rhp->rdev.stats.pd.max) 2348c2ecf20Sopenharmony_ci rhp->rdev.stats.pd.max = rhp->rdev.stats.pd.cur; 2358c2ecf20Sopenharmony_ci mutex_unlock(&rhp->rdev.stats.lock); 2368c2ecf20Sopenharmony_ci pr_debug("pdid 0x%0x ptr 0x%p\n", pdid, php); 2378c2ecf20Sopenharmony_ci return 0; 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_cistatic int c4iw_query_gid(struct ib_device *ibdev, u8 port, int index, 2418c2ecf20Sopenharmony_ci union ib_gid *gid) 2428c2ecf20Sopenharmony_ci{ 2438c2ecf20Sopenharmony_ci struct c4iw_dev *dev; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci pr_debug("ibdev %p, port %d, index %d, gid %p\n", 2468c2ecf20Sopenharmony_ci ibdev, port, index, gid); 2478c2ecf20Sopenharmony_ci if (!port) 2488c2ecf20Sopenharmony_ci return -EINVAL; 2498c2ecf20Sopenharmony_ci dev = to_c4iw_dev(ibdev); 2508c2ecf20Sopenharmony_ci memset(&(gid->raw[0]), 0, sizeof(gid->raw)); 2518c2ecf20Sopenharmony_ci memcpy(&(gid->raw[0]), dev->rdev.lldi.ports[port-1]->dev_addr, 6); 2528c2ecf20Sopenharmony_ci return 0; 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_cistatic int c4iw_query_device(struct ib_device *ibdev, struct ib_device_attr *props, 2568c2ecf20Sopenharmony_ci struct ib_udata *uhw) 2578c2ecf20Sopenharmony_ci{ 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci struct c4iw_dev *dev; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci pr_debug("ibdev %p\n", ibdev); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (uhw->inlen || uhw->outlen) 2648c2ecf20Sopenharmony_ci return -EINVAL; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci dev = to_c4iw_dev(ibdev); 2678c2ecf20Sopenharmony_ci memcpy(&props->sys_image_guid, dev->rdev.lldi.ports[0]->dev_addr, 6); 2688c2ecf20Sopenharmony_ci props->hw_ver = CHELSIO_CHIP_RELEASE(dev->rdev.lldi.adapter_type); 2698c2ecf20Sopenharmony_ci props->fw_ver = dev->rdev.lldi.fw_vers; 2708c2ecf20Sopenharmony_ci props->device_cap_flags = dev->device_cap_flags; 2718c2ecf20Sopenharmony_ci props->page_size_cap = T4_PAGESIZE_MASK; 2728c2ecf20Sopenharmony_ci props->vendor_id = (u32)dev->rdev.lldi.pdev->vendor; 2738c2ecf20Sopenharmony_ci props->vendor_part_id = (u32)dev->rdev.lldi.pdev->device; 2748c2ecf20Sopenharmony_ci props->max_mr_size = T4_MAX_MR_SIZE; 2758c2ecf20Sopenharmony_ci props->max_qp = dev->rdev.lldi.vr->qp.size / 2; 2768c2ecf20Sopenharmony_ci props->max_srq = dev->rdev.lldi.vr->srq.size; 2778c2ecf20Sopenharmony_ci props->max_qp_wr = dev->rdev.hw_queue.t4_max_qp_depth; 2788c2ecf20Sopenharmony_ci props->max_srq_wr = dev->rdev.hw_queue.t4_max_qp_depth; 2798c2ecf20Sopenharmony_ci props->max_send_sge = min(T4_MAX_SEND_SGE, T4_MAX_WRITE_SGE); 2808c2ecf20Sopenharmony_ci props->max_recv_sge = T4_MAX_RECV_SGE; 2818c2ecf20Sopenharmony_ci props->max_srq_sge = T4_MAX_RECV_SGE; 2828c2ecf20Sopenharmony_ci props->max_sge_rd = 1; 2838c2ecf20Sopenharmony_ci props->max_res_rd_atom = dev->rdev.lldi.max_ird_adapter; 2848c2ecf20Sopenharmony_ci props->max_qp_rd_atom = min(dev->rdev.lldi.max_ordird_qp, 2858c2ecf20Sopenharmony_ci c4iw_max_read_depth); 2868c2ecf20Sopenharmony_ci props->max_qp_init_rd_atom = props->max_qp_rd_atom; 2878c2ecf20Sopenharmony_ci props->max_cq = dev->rdev.lldi.vr->qp.size; 2888c2ecf20Sopenharmony_ci props->max_cqe = dev->rdev.hw_queue.t4_max_cq_depth; 2898c2ecf20Sopenharmony_ci props->max_mr = c4iw_num_stags(&dev->rdev); 2908c2ecf20Sopenharmony_ci props->max_pd = T4_MAX_NUM_PD; 2918c2ecf20Sopenharmony_ci props->local_ca_ack_delay = 0; 2928c2ecf20Sopenharmony_ci props->max_fast_reg_page_list_len = 2938c2ecf20Sopenharmony_ci t4_max_fr_depth(dev->rdev.lldi.ulptx_memwrite_dsgl && use_dsgl); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci return 0; 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic int c4iw_query_port(struct ib_device *ibdev, u8 port, 2998c2ecf20Sopenharmony_ci struct ib_port_attr *props) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci int ret = 0; 3028c2ecf20Sopenharmony_ci pr_debug("ibdev %p\n", ibdev); 3038c2ecf20Sopenharmony_ci ret = ib_get_eth_speed(ibdev, port, &props->active_speed, 3048c2ecf20Sopenharmony_ci &props->active_width); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci props->port_cap_flags = 3078c2ecf20Sopenharmony_ci IB_PORT_CM_SUP | 3088c2ecf20Sopenharmony_ci IB_PORT_SNMP_TUNNEL_SUP | 3098c2ecf20Sopenharmony_ci IB_PORT_REINIT_SUP | 3108c2ecf20Sopenharmony_ci IB_PORT_DEVICE_MGMT_SUP | 3118c2ecf20Sopenharmony_ci IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP; 3128c2ecf20Sopenharmony_ci props->gid_tbl_len = 1; 3138c2ecf20Sopenharmony_ci props->max_msg_sz = -1; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci return ret; 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic ssize_t hw_rev_show(struct device *dev, 3198c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci struct c4iw_dev *c4iw_dev = 3228c2ecf20Sopenharmony_ci rdma_device_to_drv_device(dev, struct c4iw_dev, ibdev); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci pr_debug("dev 0x%p\n", dev); 3258c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", 3268c2ecf20Sopenharmony_ci CHELSIO_CHIP_RELEASE(c4iw_dev->rdev.lldi.adapter_type)); 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(hw_rev); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_cistatic ssize_t hca_type_show(struct device *dev, 3318c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 3328c2ecf20Sopenharmony_ci{ 3338c2ecf20Sopenharmony_ci struct c4iw_dev *c4iw_dev = 3348c2ecf20Sopenharmony_ci rdma_device_to_drv_device(dev, struct c4iw_dev, ibdev); 3358c2ecf20Sopenharmony_ci struct ethtool_drvinfo info; 3368c2ecf20Sopenharmony_ci struct net_device *lldev = c4iw_dev->rdev.lldi.ports[0]; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci pr_debug("dev 0x%p\n", dev); 3398c2ecf20Sopenharmony_ci lldev->ethtool_ops->get_drvinfo(lldev, &info); 3408c2ecf20Sopenharmony_ci return sprintf(buf, "%s\n", info.driver); 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(hca_type); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic ssize_t board_id_show(struct device *dev, struct device_attribute *attr, 3458c2ecf20Sopenharmony_ci char *buf) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci struct c4iw_dev *c4iw_dev = 3488c2ecf20Sopenharmony_ci rdma_device_to_drv_device(dev, struct c4iw_dev, ibdev); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci pr_debug("dev 0x%p\n", dev); 3518c2ecf20Sopenharmony_ci return sprintf(buf, "%x.%x\n", c4iw_dev->rdev.lldi.pdev->vendor, 3528c2ecf20Sopenharmony_ci c4iw_dev->rdev.lldi.pdev->device); 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(board_id); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cienum counters { 3578c2ecf20Sopenharmony_ci IP4INSEGS, 3588c2ecf20Sopenharmony_ci IP4OUTSEGS, 3598c2ecf20Sopenharmony_ci IP4RETRANSSEGS, 3608c2ecf20Sopenharmony_ci IP4OUTRSTS, 3618c2ecf20Sopenharmony_ci IP6INSEGS, 3628c2ecf20Sopenharmony_ci IP6OUTSEGS, 3638c2ecf20Sopenharmony_ci IP6RETRANSSEGS, 3648c2ecf20Sopenharmony_ci IP6OUTRSTS, 3658c2ecf20Sopenharmony_ci NR_COUNTERS 3668c2ecf20Sopenharmony_ci}; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistatic const char * const names[] = { 3698c2ecf20Sopenharmony_ci [IP4INSEGS] = "ip4InSegs", 3708c2ecf20Sopenharmony_ci [IP4OUTSEGS] = "ip4OutSegs", 3718c2ecf20Sopenharmony_ci [IP4RETRANSSEGS] = "ip4RetransSegs", 3728c2ecf20Sopenharmony_ci [IP4OUTRSTS] = "ip4OutRsts", 3738c2ecf20Sopenharmony_ci [IP6INSEGS] = "ip6InSegs", 3748c2ecf20Sopenharmony_ci [IP6OUTSEGS] = "ip6OutSegs", 3758c2ecf20Sopenharmony_ci [IP6RETRANSSEGS] = "ip6RetransSegs", 3768c2ecf20Sopenharmony_ci [IP6OUTRSTS] = "ip6OutRsts" 3778c2ecf20Sopenharmony_ci}; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cistatic struct rdma_hw_stats *c4iw_alloc_stats(struct ib_device *ibdev, 3808c2ecf20Sopenharmony_ci u8 port_num) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(names) != NR_COUNTERS); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci if (port_num != 0) 3858c2ecf20Sopenharmony_ci return NULL; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci return rdma_alloc_hw_stats_struct(names, NR_COUNTERS, 3888c2ecf20Sopenharmony_ci RDMA_HW_STATS_DEFAULT_LIFESPAN); 3898c2ecf20Sopenharmony_ci} 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_cistatic int c4iw_get_mib(struct ib_device *ibdev, 3928c2ecf20Sopenharmony_ci struct rdma_hw_stats *stats, 3938c2ecf20Sopenharmony_ci u8 port, int index) 3948c2ecf20Sopenharmony_ci{ 3958c2ecf20Sopenharmony_ci struct tp_tcp_stats v4, v6; 3968c2ecf20Sopenharmony_ci struct c4iw_dev *c4iw_dev = to_c4iw_dev(ibdev); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci cxgb4_get_tcp_stats(c4iw_dev->rdev.lldi.pdev, &v4, &v6); 3998c2ecf20Sopenharmony_ci stats->value[IP4INSEGS] = v4.tcp_in_segs; 4008c2ecf20Sopenharmony_ci stats->value[IP4OUTSEGS] = v4.tcp_out_segs; 4018c2ecf20Sopenharmony_ci stats->value[IP4RETRANSSEGS] = v4.tcp_retrans_segs; 4028c2ecf20Sopenharmony_ci stats->value[IP4OUTRSTS] = v4.tcp_out_rsts; 4038c2ecf20Sopenharmony_ci stats->value[IP6INSEGS] = v6.tcp_in_segs; 4048c2ecf20Sopenharmony_ci stats->value[IP6OUTSEGS] = v6.tcp_out_segs; 4058c2ecf20Sopenharmony_ci stats->value[IP6RETRANSSEGS] = v6.tcp_retrans_segs; 4068c2ecf20Sopenharmony_ci stats->value[IP6OUTRSTS] = v6.tcp_out_rsts; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci return stats->num_counters; 4098c2ecf20Sopenharmony_ci} 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_cistatic struct attribute *c4iw_class_attributes[] = { 4128c2ecf20Sopenharmony_ci &dev_attr_hw_rev.attr, 4138c2ecf20Sopenharmony_ci &dev_attr_hca_type.attr, 4148c2ecf20Sopenharmony_ci &dev_attr_board_id.attr, 4158c2ecf20Sopenharmony_ci NULL 4168c2ecf20Sopenharmony_ci}; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_cistatic const struct attribute_group c4iw_attr_group = { 4198c2ecf20Sopenharmony_ci .attrs = c4iw_class_attributes, 4208c2ecf20Sopenharmony_ci}; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_cistatic int c4iw_port_immutable(struct ib_device *ibdev, u8 port_num, 4238c2ecf20Sopenharmony_ci struct ib_port_immutable *immutable) 4248c2ecf20Sopenharmony_ci{ 4258c2ecf20Sopenharmony_ci struct ib_port_attr attr; 4268c2ecf20Sopenharmony_ci int err; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci immutable->core_cap_flags = RDMA_CORE_PORT_IWARP; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci err = ib_query_port(ibdev, port_num, &attr); 4318c2ecf20Sopenharmony_ci if (err) 4328c2ecf20Sopenharmony_ci return err; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci immutable->gid_tbl_len = attr.gid_tbl_len; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci return 0; 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_cistatic void get_dev_fw_str(struct ib_device *dev, char *str) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci struct c4iw_dev *c4iw_dev = container_of(dev, struct c4iw_dev, 4428c2ecf20Sopenharmony_ci ibdev); 4438c2ecf20Sopenharmony_ci pr_debug("dev 0x%p\n", dev); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci snprintf(str, IB_FW_VERSION_NAME_MAX, "%u.%u.%u.%u", 4468c2ecf20Sopenharmony_ci FW_HDR_FW_VER_MAJOR_G(c4iw_dev->rdev.lldi.fw_vers), 4478c2ecf20Sopenharmony_ci FW_HDR_FW_VER_MINOR_G(c4iw_dev->rdev.lldi.fw_vers), 4488c2ecf20Sopenharmony_ci FW_HDR_FW_VER_MICRO_G(c4iw_dev->rdev.lldi.fw_vers), 4498c2ecf20Sopenharmony_ci FW_HDR_FW_VER_BUILD_G(c4iw_dev->rdev.lldi.fw_vers)); 4508c2ecf20Sopenharmony_ci} 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_cistatic const struct ib_device_ops c4iw_dev_ops = { 4538c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 4548c2ecf20Sopenharmony_ci .driver_id = RDMA_DRIVER_CXGB4, 4558c2ecf20Sopenharmony_ci .uverbs_abi_ver = C4IW_UVERBS_ABI_VERSION, 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci .alloc_hw_stats = c4iw_alloc_stats, 4588c2ecf20Sopenharmony_ci .alloc_mr = c4iw_alloc_mr, 4598c2ecf20Sopenharmony_ci .alloc_mw = c4iw_alloc_mw, 4608c2ecf20Sopenharmony_ci .alloc_pd = c4iw_allocate_pd, 4618c2ecf20Sopenharmony_ci .alloc_ucontext = c4iw_alloc_ucontext, 4628c2ecf20Sopenharmony_ci .create_cq = c4iw_create_cq, 4638c2ecf20Sopenharmony_ci .create_qp = c4iw_create_qp, 4648c2ecf20Sopenharmony_ci .create_srq = c4iw_create_srq, 4658c2ecf20Sopenharmony_ci .dealloc_mw = c4iw_dealloc_mw, 4668c2ecf20Sopenharmony_ci .dealloc_pd = c4iw_deallocate_pd, 4678c2ecf20Sopenharmony_ci .dealloc_ucontext = c4iw_dealloc_ucontext, 4688c2ecf20Sopenharmony_ci .dereg_mr = c4iw_dereg_mr, 4698c2ecf20Sopenharmony_ci .destroy_cq = c4iw_destroy_cq, 4708c2ecf20Sopenharmony_ci .destroy_qp = c4iw_destroy_qp, 4718c2ecf20Sopenharmony_ci .destroy_srq = c4iw_destroy_srq, 4728c2ecf20Sopenharmony_ci .fill_res_cq_entry = c4iw_fill_res_cq_entry, 4738c2ecf20Sopenharmony_ci .fill_res_cm_id_entry = c4iw_fill_res_cm_id_entry, 4748c2ecf20Sopenharmony_ci .fill_res_mr_entry = c4iw_fill_res_mr_entry, 4758c2ecf20Sopenharmony_ci .get_dev_fw_str = get_dev_fw_str, 4768c2ecf20Sopenharmony_ci .get_dma_mr = c4iw_get_dma_mr, 4778c2ecf20Sopenharmony_ci .get_hw_stats = c4iw_get_mib, 4788c2ecf20Sopenharmony_ci .get_port_immutable = c4iw_port_immutable, 4798c2ecf20Sopenharmony_ci .iw_accept = c4iw_accept_cr, 4808c2ecf20Sopenharmony_ci .iw_add_ref = c4iw_qp_add_ref, 4818c2ecf20Sopenharmony_ci .iw_connect = c4iw_connect, 4828c2ecf20Sopenharmony_ci .iw_create_listen = c4iw_create_listen, 4838c2ecf20Sopenharmony_ci .iw_destroy_listen = c4iw_destroy_listen, 4848c2ecf20Sopenharmony_ci .iw_get_qp = c4iw_get_qp, 4858c2ecf20Sopenharmony_ci .iw_reject = c4iw_reject_cr, 4868c2ecf20Sopenharmony_ci .iw_rem_ref = c4iw_qp_rem_ref, 4878c2ecf20Sopenharmony_ci .map_mr_sg = c4iw_map_mr_sg, 4888c2ecf20Sopenharmony_ci .mmap = c4iw_mmap, 4898c2ecf20Sopenharmony_ci .modify_qp = c4iw_ib_modify_qp, 4908c2ecf20Sopenharmony_ci .modify_srq = c4iw_modify_srq, 4918c2ecf20Sopenharmony_ci .poll_cq = c4iw_poll_cq, 4928c2ecf20Sopenharmony_ci .post_recv = c4iw_post_receive, 4938c2ecf20Sopenharmony_ci .post_send = c4iw_post_send, 4948c2ecf20Sopenharmony_ci .post_srq_recv = c4iw_post_srq_recv, 4958c2ecf20Sopenharmony_ci .query_device = c4iw_query_device, 4968c2ecf20Sopenharmony_ci .query_gid = c4iw_query_gid, 4978c2ecf20Sopenharmony_ci .query_port = c4iw_query_port, 4988c2ecf20Sopenharmony_ci .query_qp = c4iw_ib_query_qp, 4998c2ecf20Sopenharmony_ci .reg_user_mr = c4iw_reg_user_mr, 5008c2ecf20Sopenharmony_ci .req_notify_cq = c4iw_arm_cq, 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci INIT_RDMA_OBJ_SIZE(ib_cq, c4iw_cq, ibcq), 5038c2ecf20Sopenharmony_ci INIT_RDMA_OBJ_SIZE(ib_mw, c4iw_mw, ibmw), 5048c2ecf20Sopenharmony_ci INIT_RDMA_OBJ_SIZE(ib_pd, c4iw_pd, ibpd), 5058c2ecf20Sopenharmony_ci INIT_RDMA_OBJ_SIZE(ib_srq, c4iw_srq, ibsrq), 5068c2ecf20Sopenharmony_ci INIT_RDMA_OBJ_SIZE(ib_ucontext, c4iw_ucontext, ibucontext), 5078c2ecf20Sopenharmony_ci}; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_cistatic int set_netdevs(struct ib_device *ib_dev, struct c4iw_rdev *rdev) 5108c2ecf20Sopenharmony_ci{ 5118c2ecf20Sopenharmony_ci int ret; 5128c2ecf20Sopenharmony_ci int i; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci for (i = 0; i < rdev->lldi.nports; i++) { 5158c2ecf20Sopenharmony_ci ret = ib_device_set_netdev(ib_dev, rdev->lldi.ports[i], 5168c2ecf20Sopenharmony_ci i + 1); 5178c2ecf20Sopenharmony_ci if (ret) 5188c2ecf20Sopenharmony_ci return ret; 5198c2ecf20Sopenharmony_ci } 5208c2ecf20Sopenharmony_ci return 0; 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_civoid c4iw_register_device(struct work_struct *work) 5248c2ecf20Sopenharmony_ci{ 5258c2ecf20Sopenharmony_ci int ret; 5268c2ecf20Sopenharmony_ci struct uld_ctx *ctx = container_of(work, struct uld_ctx, reg_work); 5278c2ecf20Sopenharmony_ci struct c4iw_dev *dev = ctx->dev; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci pr_debug("c4iw_dev %p\n", dev); 5308c2ecf20Sopenharmony_ci memset(&dev->ibdev.node_guid, 0, sizeof(dev->ibdev.node_guid)); 5318c2ecf20Sopenharmony_ci memcpy(&dev->ibdev.node_guid, dev->rdev.lldi.ports[0]->dev_addr, 6); 5328c2ecf20Sopenharmony_ci dev->device_cap_flags = IB_DEVICE_LOCAL_DMA_LKEY | IB_DEVICE_MEM_WINDOW; 5338c2ecf20Sopenharmony_ci if (fastreg_support) 5348c2ecf20Sopenharmony_ci dev->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS; 5358c2ecf20Sopenharmony_ci dev->ibdev.local_dma_lkey = 0; 5368c2ecf20Sopenharmony_ci dev->ibdev.uverbs_cmd_mask = 5378c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | 5388c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | 5398c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | 5408c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | 5418c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | 5428c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_REG_MR) | 5438c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_DEREG_MR) | 5448c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | 5458c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | 5468c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | 5478c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) | 5488c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_CREATE_QP) | 5498c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | 5508c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_QUERY_QP) | 5518c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_POLL_CQ) | 5528c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | 5538c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_POST_SEND) | 5548c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_POST_RECV) | 5558c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | 5568c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | 5578c2ecf20Sopenharmony_ci (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ); 5588c2ecf20Sopenharmony_ci dev->ibdev.node_type = RDMA_NODE_RNIC; 5598c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(C4IW_NODE_DESC) > IB_DEVICE_NODE_DESC_MAX); 5608c2ecf20Sopenharmony_ci memcpy(dev->ibdev.node_desc, C4IW_NODE_DESC, sizeof(C4IW_NODE_DESC)); 5618c2ecf20Sopenharmony_ci dev->ibdev.phys_port_cnt = dev->rdev.lldi.nports; 5628c2ecf20Sopenharmony_ci dev->ibdev.num_comp_vectors = dev->rdev.lldi.nciq; 5638c2ecf20Sopenharmony_ci dev->ibdev.dev.parent = &dev->rdev.lldi.pdev->dev; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci memcpy(dev->ibdev.iw_ifname, dev->rdev.lldi.ports[0]->name, 5668c2ecf20Sopenharmony_ci sizeof(dev->ibdev.iw_ifname)); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci rdma_set_device_sysfs_group(&dev->ibdev, &c4iw_attr_group); 5698c2ecf20Sopenharmony_ci ib_set_device_ops(&dev->ibdev, &c4iw_dev_ops); 5708c2ecf20Sopenharmony_ci ret = set_netdevs(&dev->ibdev, &dev->rdev); 5718c2ecf20Sopenharmony_ci if (ret) 5728c2ecf20Sopenharmony_ci goto err_dealloc_ctx; 5738c2ecf20Sopenharmony_ci dma_set_max_seg_size(&dev->rdev.lldi.pdev->dev, UINT_MAX); 5748c2ecf20Sopenharmony_ci ret = ib_register_device(&dev->ibdev, "cxgb4_%d", 5758c2ecf20Sopenharmony_ci &dev->rdev.lldi.pdev->dev); 5768c2ecf20Sopenharmony_ci if (ret) 5778c2ecf20Sopenharmony_ci goto err_dealloc_ctx; 5788c2ecf20Sopenharmony_ci return; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_cierr_dealloc_ctx: 5818c2ecf20Sopenharmony_ci pr_err("%s - Failed registering iwarp device: %d\n", 5828c2ecf20Sopenharmony_ci pci_name(ctx->lldi.pdev), ret); 5838c2ecf20Sopenharmony_ci c4iw_dealloc(ctx); 5848c2ecf20Sopenharmony_ci return; 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_civoid c4iw_unregister_device(struct c4iw_dev *dev) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci pr_debug("c4iw_dev %p\n", dev); 5908c2ecf20Sopenharmony_ci ib_unregister_device(&dev->ibdev); 5918c2ecf20Sopenharmony_ci return; 5928c2ecf20Sopenharmony_ci} 593