1e3cf00d0SUpinder Malhi /* 2e3cf00d0SUpinder Malhi * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved. 3e3cf00d0SUpinder Malhi * 43805eadeSJeff Squyres * This software is available to you under a choice of one of two 53805eadeSJeff Squyres * licenses. You may choose to be licensed under the terms of the GNU 63805eadeSJeff Squyres * General Public License (GPL) Version 2, available from the file 73805eadeSJeff Squyres * COPYING in the main directory of this source tree, or the 83805eadeSJeff Squyres * BSD license below: 93805eadeSJeff Squyres * 103805eadeSJeff Squyres * Redistribution and use in source and binary forms, with or 113805eadeSJeff Squyres * without modification, are permitted provided that the following 123805eadeSJeff Squyres * conditions are met: 133805eadeSJeff Squyres * 143805eadeSJeff Squyres * - Redistributions of source code must retain the above 153805eadeSJeff Squyres * copyright notice, this list of conditions and the following 163805eadeSJeff Squyres * disclaimer. 173805eadeSJeff Squyres * 183805eadeSJeff Squyres * - Redistributions in binary form must reproduce the above 193805eadeSJeff Squyres * copyright notice, this list of conditions and the following 203805eadeSJeff Squyres * disclaimer in the documentation and/or other materials 213805eadeSJeff Squyres * provided with the distribution. 22e3cf00d0SUpinder Malhi * 23e3cf00d0SUpinder Malhi * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24e3cf00d0SUpinder Malhi * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25e3cf00d0SUpinder Malhi * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26e3cf00d0SUpinder Malhi * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27e3cf00d0SUpinder Malhi * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28e3cf00d0SUpinder Malhi * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29e3cf00d0SUpinder Malhi * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30e3cf00d0SUpinder Malhi * SOFTWARE. 31e3cf00d0SUpinder Malhi * 32e3cf00d0SUpinder Malhi * Author: Upinder Malhi <umalhi@cisco.com> 33e3cf00d0SUpinder Malhi * Author: Anant Deepak <anadeepa@cisco.com> 34e3cf00d0SUpinder Malhi * Author: Cesare Cantu' <cantuc@cisco.com> 35e3cf00d0SUpinder Malhi * Author: Jeff Squyres <jsquyres@cisco.com> 36e3cf00d0SUpinder Malhi * Author: Kiran Thirumalai <kithirum@cisco.com> 37e3cf00d0SUpinder Malhi * Author: Xuyang Wang <xuywang@cisco.com> 38e3cf00d0SUpinder Malhi * Author: Reese Faucette <rfaucett@cisco.com> 39e3cf00d0SUpinder Malhi * 40e3cf00d0SUpinder Malhi */ 41e3cf00d0SUpinder Malhi 42e3cf00d0SUpinder Malhi #include <linux/module.h> 43c7845bcaSUpinder Malhi #include <linux/inetdevice.h> 44e3cf00d0SUpinder Malhi #include <linux/init.h> 45e3cf00d0SUpinder Malhi #include <linux/slab.h> 46e3cf00d0SUpinder Malhi #include <linux/errno.h> 47e3cf00d0SUpinder Malhi #include <linux/pci.h> 48e3cf00d0SUpinder Malhi #include <linux/netdevice.h> 49e3cf00d0SUpinder Malhi 50e3cf00d0SUpinder Malhi #include <rdma/ib_user_verbs.h> 51e3cf00d0SUpinder Malhi #include <rdma/ib_addr.h> 52e3cf00d0SUpinder Malhi 53e3cf00d0SUpinder Malhi #include "usnic_abi.h" 54e3cf00d0SUpinder Malhi #include "usnic_common_util.h" 55e3cf00d0SUpinder Malhi #include "usnic_ib.h" 56e3cf00d0SUpinder Malhi #include "usnic_ib_qp_grp.h" 57e3cf00d0SUpinder Malhi #include "usnic_log.h" 58e3cf00d0SUpinder Malhi #include "usnic_fwd.h" 59e3cf00d0SUpinder Malhi #include "usnic_debugfs.h" 60e3cf00d0SUpinder Malhi #include "usnic_ib_verbs.h" 61e3cf00d0SUpinder Malhi #include "usnic_transport.h" 62e3cf00d0SUpinder Malhi #include "usnic_uiom.h" 63e3cf00d0SUpinder Malhi #include "usnic_ib_sysfs.h" 64e3cf00d0SUpinder Malhi 65e3cf00d0SUpinder Malhi unsigned int usnic_log_lvl = USNIC_LOG_LVL_ERR; 66e3cf00d0SUpinder Malhi unsigned int usnic_ib_share_vf = 1; 67e3cf00d0SUpinder Malhi 68e3cf00d0SUpinder Malhi static const char usnic_version[] = 69e3cf00d0SUpinder Malhi DRV_NAME ": Cisco VIC (USNIC) Verbs Driver v" 70e3cf00d0SUpinder Malhi DRV_VERSION " (" DRV_RELDATE ")\n"; 71e3cf00d0SUpinder Malhi 72e3cf00d0SUpinder Malhi static DEFINE_MUTEX(usnic_ib_ibdev_list_lock); 73e3cf00d0SUpinder Malhi static LIST_HEAD(usnic_ib_ibdev_list); 74e3cf00d0SUpinder Malhi 75e3cf00d0SUpinder Malhi /* Callback dump funcs */ 76e3cf00d0SUpinder Malhi static int usnic_ib_dump_vf_hdr(void *obj, char *buf, int buf_sz) 77e3cf00d0SUpinder Malhi { 78e3cf00d0SUpinder Malhi struct usnic_ib_vf *vf = obj; 799de69861SJason Gunthorpe return scnprintf(buf, buf_sz, "PF: %s ", dev_name(&vf->pf->ib_dev.dev)); 80e3cf00d0SUpinder Malhi } 81e3cf00d0SUpinder Malhi /* End callback dump funcs */ 82e3cf00d0SUpinder Malhi 83e3cf00d0SUpinder Malhi static void usnic_ib_dump_vf(struct usnic_ib_vf *vf, char *buf, int buf_sz) 84e3cf00d0SUpinder Malhi { 85e3cf00d0SUpinder Malhi usnic_vnic_dump(vf->vnic, buf, buf_sz, vf, 86e3cf00d0SUpinder Malhi usnic_ib_dump_vf_hdr, 87e3cf00d0SUpinder Malhi usnic_ib_qp_grp_dump_hdr, usnic_ib_qp_grp_dump_rows); 88e3cf00d0SUpinder Malhi } 89e3cf00d0SUpinder Malhi 90e3cf00d0SUpinder Malhi void usnic_ib_log_vf(struct usnic_ib_vf *vf) 91e3cf00d0SUpinder Malhi { 92e3cf00d0SUpinder Malhi char buf[1000]; 93e3cf00d0SUpinder Malhi usnic_ib_dump_vf(vf, buf, sizeof(buf)); 94e3cf00d0SUpinder Malhi usnic_dbg("%s\n", buf); 95e3cf00d0SUpinder Malhi } 96e3cf00d0SUpinder Malhi 97e3cf00d0SUpinder Malhi /* Start of netdev section */ 98e3cf00d0SUpinder Malhi static void usnic_ib_qp_grp_modify_active_to_err(struct usnic_ib_dev *us_ibdev) 99e3cf00d0SUpinder Malhi { 100e3cf00d0SUpinder Malhi struct usnic_ib_ucontext *ctx; 101e3cf00d0SUpinder Malhi struct usnic_ib_qp_grp *qp_grp; 102e3cf00d0SUpinder Malhi enum ib_qp_state cur_state; 103e3cf00d0SUpinder Malhi int status; 104e3cf00d0SUpinder Malhi 105e3cf00d0SUpinder Malhi BUG_ON(!mutex_is_locked(&us_ibdev->usdev_lock)); 106e3cf00d0SUpinder Malhi 107e3cf00d0SUpinder Malhi list_for_each_entry(ctx, &us_ibdev->ctx_list, link) { 108e3cf00d0SUpinder Malhi list_for_each_entry(qp_grp, &ctx->qp_grp_list, link) { 109e3cf00d0SUpinder Malhi cur_state = qp_grp->state; 110e3cf00d0SUpinder Malhi if (cur_state == IB_QPS_INIT || 111e3cf00d0SUpinder Malhi cur_state == IB_QPS_RTR || 112e3cf00d0SUpinder Malhi cur_state == IB_QPS_RTS) { 113e3cf00d0SUpinder Malhi status = usnic_ib_qp_grp_modify(qp_grp, 114e3cf00d0SUpinder Malhi IB_QPS_ERR, 115e3cf00d0SUpinder Malhi NULL); 116e3cf00d0SUpinder Malhi if (status) { 117e3cf00d0SUpinder Malhi usnic_err("Failed to transistion qp grp %u from %s to %s\n", 118e3cf00d0SUpinder Malhi qp_grp->grp_id, 119e3cf00d0SUpinder Malhi usnic_ib_qp_grp_state_to_string 120e3cf00d0SUpinder Malhi (cur_state), 121e3cf00d0SUpinder Malhi usnic_ib_qp_grp_state_to_string 122e3cf00d0SUpinder Malhi (IB_QPS_ERR)); 123e3cf00d0SUpinder Malhi } 124e3cf00d0SUpinder Malhi } 125e3cf00d0SUpinder Malhi } 126e3cf00d0SUpinder Malhi } 127e3cf00d0SUpinder Malhi } 128e3cf00d0SUpinder Malhi 129e3cf00d0SUpinder Malhi static void usnic_ib_handle_usdev_event(struct usnic_ib_dev *us_ibdev, 130e3cf00d0SUpinder Malhi unsigned long event) 131e3cf00d0SUpinder Malhi { 132e3cf00d0SUpinder Malhi struct net_device *netdev; 133e3cf00d0SUpinder Malhi struct ib_event ib_event; 134e3cf00d0SUpinder Malhi 135e3cf00d0SUpinder Malhi memset(&ib_event, 0, sizeof(ib_event)); 136e3cf00d0SUpinder Malhi 137e3cf00d0SUpinder Malhi mutex_lock(&us_ibdev->usdev_lock); 138e3cf00d0SUpinder Malhi netdev = us_ibdev->netdev; 139e3cf00d0SUpinder Malhi switch (event) { 140e3cf00d0SUpinder Malhi case NETDEV_REBOOT: 1419de69861SJason Gunthorpe usnic_info("PF Reset on %s\n", dev_name(&us_ibdev->ib_dev.dev)); 142e3cf00d0SUpinder Malhi usnic_ib_qp_grp_modify_active_to_err(us_ibdev); 143e3cf00d0SUpinder Malhi ib_event.event = IB_EVENT_PORT_ERR; 144e3cf00d0SUpinder Malhi ib_event.device = &us_ibdev->ib_dev; 145e3cf00d0SUpinder Malhi ib_event.element.port_num = 1; 146e3cf00d0SUpinder Malhi ib_dispatch_event(&ib_event); 147e3cf00d0SUpinder Malhi break; 148e3cf00d0SUpinder Malhi case NETDEV_UP: 149e3cf00d0SUpinder Malhi case NETDEV_DOWN: 150e3cf00d0SUpinder Malhi case NETDEV_CHANGE: 1518af94ac6SUpinder Malhi if (!us_ibdev->ufdev->link_up && 1528af94ac6SUpinder Malhi netif_carrier_ok(netdev)) { 1538af94ac6SUpinder Malhi usnic_fwd_carrier_up(us_ibdev->ufdev); 1549de69861SJason Gunthorpe usnic_info("Link UP on %s\n", 1559de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 156e3cf00d0SUpinder Malhi ib_event.event = IB_EVENT_PORT_ACTIVE; 157e3cf00d0SUpinder Malhi ib_event.device = &us_ibdev->ib_dev; 158e3cf00d0SUpinder Malhi ib_event.element.port_num = 1; 159e3cf00d0SUpinder Malhi ib_dispatch_event(&ib_event); 1608af94ac6SUpinder Malhi } else if (us_ibdev->ufdev->link_up && 1618af94ac6SUpinder Malhi !netif_carrier_ok(netdev)) { 1628af94ac6SUpinder Malhi usnic_fwd_carrier_down(us_ibdev->ufdev); 1639de69861SJason Gunthorpe usnic_info("Link DOWN on %s\n", 1649de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 165e3cf00d0SUpinder Malhi usnic_ib_qp_grp_modify_active_to_err(us_ibdev); 166e3cf00d0SUpinder Malhi ib_event.event = IB_EVENT_PORT_ERR; 167e3cf00d0SUpinder Malhi ib_event.device = &us_ibdev->ib_dev; 168e3cf00d0SUpinder Malhi ib_event.element.port_num = 1; 169e3cf00d0SUpinder Malhi ib_dispatch_event(&ib_event); 170e3cf00d0SUpinder Malhi } else { 171c30392abSRoland Dreier usnic_dbg("Ignoring %s on %s\n", 1723e0c2dbfSKirill Tkhai netdev_cmd_to_name(event), 1739de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 174e3cf00d0SUpinder Malhi } 175e3cf00d0SUpinder Malhi break; 176e3cf00d0SUpinder Malhi case NETDEV_CHANGEADDR: 1778af94ac6SUpinder Malhi if (!memcmp(us_ibdev->ufdev->mac, netdev->dev_addr, 1788af94ac6SUpinder Malhi sizeof(us_ibdev->ufdev->mac))) { 179c30392abSRoland Dreier usnic_dbg("Ignoring addr change on %s\n", 1809de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 181e3cf00d0SUpinder Malhi } else { 182e3cf00d0SUpinder Malhi usnic_info(" %s old mac: %pM new mac: %pM\n", 1839de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev), 1848af94ac6SUpinder Malhi us_ibdev->ufdev->mac, 185e3cf00d0SUpinder Malhi netdev->dev_addr); 1868af94ac6SUpinder Malhi usnic_fwd_set_mac(us_ibdev->ufdev, netdev->dev_addr); 187e3cf00d0SUpinder Malhi usnic_ib_qp_grp_modify_active_to_err(us_ibdev); 188e3cf00d0SUpinder Malhi ib_event.event = IB_EVENT_GID_CHANGE; 189e3cf00d0SUpinder Malhi ib_event.device = &us_ibdev->ib_dev; 190e3cf00d0SUpinder Malhi ib_event.element.port_num = 1; 191e3cf00d0SUpinder Malhi ib_dispatch_event(&ib_event); 192e3cf00d0SUpinder Malhi } 193e3cf00d0SUpinder Malhi 194e3cf00d0SUpinder Malhi break; 195e3cf00d0SUpinder Malhi case NETDEV_CHANGEMTU: 1968af94ac6SUpinder Malhi if (us_ibdev->ufdev->mtu != netdev->mtu) { 197e3cf00d0SUpinder Malhi usnic_info("MTU Change on %s old: %u new: %u\n", 1989de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev), 1998af94ac6SUpinder Malhi us_ibdev->ufdev->mtu, netdev->mtu); 2008af94ac6SUpinder Malhi usnic_fwd_set_mtu(us_ibdev->ufdev, netdev->mtu); 201e3cf00d0SUpinder Malhi usnic_ib_qp_grp_modify_active_to_err(us_ibdev); 202e3cf00d0SUpinder Malhi } else { 203e3cf00d0SUpinder Malhi usnic_dbg("Ignoring MTU change on %s\n", 2049de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 205e3cf00d0SUpinder Malhi } 206e3cf00d0SUpinder Malhi break; 207e3cf00d0SUpinder Malhi default: 208c30392abSRoland Dreier usnic_dbg("Ignoring event %s on %s", 2093e0c2dbfSKirill Tkhai netdev_cmd_to_name(event), 2109de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 211e3cf00d0SUpinder Malhi } 212e3cf00d0SUpinder Malhi mutex_unlock(&us_ibdev->usdev_lock); 213e3cf00d0SUpinder Malhi } 214e3cf00d0SUpinder Malhi 215e3cf00d0SUpinder Malhi static int usnic_ib_netdevice_event(struct notifier_block *notifier, 216e3cf00d0SUpinder Malhi unsigned long event, void *ptr) 217e3cf00d0SUpinder Malhi { 218e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev; 219e3cf00d0SUpinder Malhi 220e3cf00d0SUpinder Malhi struct net_device *netdev = netdev_notifier_info_to_dev(ptr); 221e3cf00d0SUpinder Malhi 222e3cf00d0SUpinder Malhi mutex_lock(&usnic_ib_ibdev_list_lock); 223e3cf00d0SUpinder Malhi list_for_each_entry(us_ibdev, &usnic_ib_ibdev_list, ib_dev_link) { 224e3cf00d0SUpinder Malhi if (us_ibdev->netdev == netdev) { 225e3cf00d0SUpinder Malhi usnic_ib_handle_usdev_event(us_ibdev, event); 226e3cf00d0SUpinder Malhi break; 227e3cf00d0SUpinder Malhi } 228e3cf00d0SUpinder Malhi } 229e3cf00d0SUpinder Malhi mutex_unlock(&usnic_ib_ibdev_list_lock); 230e3cf00d0SUpinder Malhi 231e3cf00d0SUpinder Malhi return NOTIFY_DONE; 232e3cf00d0SUpinder Malhi } 233e3cf00d0SUpinder Malhi 234e3cf00d0SUpinder Malhi static struct notifier_block usnic_ib_netdevice_notifier = { 235e3cf00d0SUpinder Malhi .notifier_call = usnic_ib_netdevice_event 236e3cf00d0SUpinder Malhi }; 237e3cf00d0SUpinder Malhi /* End of netdev section */ 238e3cf00d0SUpinder Malhi 239c7845bcaSUpinder Malhi /* Start of inet section */ 240c7845bcaSUpinder Malhi static int usnic_ib_handle_inet_event(struct usnic_ib_dev *us_ibdev, 241c7845bcaSUpinder Malhi unsigned long event, void *ptr) 242c7845bcaSUpinder Malhi { 243c7845bcaSUpinder Malhi struct in_ifaddr *ifa = ptr; 244c7845bcaSUpinder Malhi struct ib_event ib_event; 245c7845bcaSUpinder Malhi 246c7845bcaSUpinder Malhi mutex_lock(&us_ibdev->usdev_lock); 247c7845bcaSUpinder Malhi 248c7845bcaSUpinder Malhi switch (event) { 249c7845bcaSUpinder Malhi case NETDEV_DOWN: 250c7845bcaSUpinder Malhi usnic_info("%s via ip notifiers", 2513e0c2dbfSKirill Tkhai netdev_cmd_to_name(event)); 252c7845bcaSUpinder Malhi usnic_fwd_del_ipaddr(us_ibdev->ufdev); 253c7845bcaSUpinder Malhi usnic_ib_qp_grp_modify_active_to_err(us_ibdev); 254c7845bcaSUpinder Malhi ib_event.event = IB_EVENT_GID_CHANGE; 255c7845bcaSUpinder Malhi ib_event.device = &us_ibdev->ib_dev; 256c7845bcaSUpinder Malhi ib_event.element.port_num = 1; 257c7845bcaSUpinder Malhi ib_dispatch_event(&ib_event); 258c7845bcaSUpinder Malhi break; 259c7845bcaSUpinder Malhi case NETDEV_UP: 260c7845bcaSUpinder Malhi usnic_fwd_add_ipaddr(us_ibdev->ufdev, ifa->ifa_address); 261c7845bcaSUpinder Malhi usnic_info("%s via ip notifiers: ip %pI4", 2623e0c2dbfSKirill Tkhai netdev_cmd_to_name(event), 263c7845bcaSUpinder Malhi &us_ibdev->ufdev->inaddr); 264c7845bcaSUpinder Malhi ib_event.event = IB_EVENT_GID_CHANGE; 265c7845bcaSUpinder Malhi ib_event.device = &us_ibdev->ib_dev; 266c7845bcaSUpinder Malhi ib_event.element.port_num = 1; 267c7845bcaSUpinder Malhi ib_dispatch_event(&ib_event); 268c7845bcaSUpinder Malhi break; 269c7845bcaSUpinder Malhi default: 270c30392abSRoland Dreier usnic_info("Ignoring event %s on %s", 2713e0c2dbfSKirill Tkhai netdev_cmd_to_name(event), 2729de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 273c7845bcaSUpinder Malhi } 274c7845bcaSUpinder Malhi mutex_unlock(&us_ibdev->usdev_lock); 275c7845bcaSUpinder Malhi 276c7845bcaSUpinder Malhi return NOTIFY_DONE; 277c7845bcaSUpinder Malhi } 278c7845bcaSUpinder Malhi 279c7845bcaSUpinder Malhi static int usnic_ib_inetaddr_event(struct notifier_block *notifier, 280c7845bcaSUpinder Malhi unsigned long event, void *ptr) 281c7845bcaSUpinder Malhi { 282c7845bcaSUpinder Malhi struct usnic_ib_dev *us_ibdev; 283c7845bcaSUpinder Malhi struct in_ifaddr *ifa = ptr; 284c7845bcaSUpinder Malhi struct net_device *netdev = ifa->ifa_dev->dev; 285c7845bcaSUpinder Malhi 286c7845bcaSUpinder Malhi mutex_lock(&usnic_ib_ibdev_list_lock); 287c7845bcaSUpinder Malhi list_for_each_entry(us_ibdev, &usnic_ib_ibdev_list, ib_dev_link) { 288c7845bcaSUpinder Malhi if (us_ibdev->netdev == netdev) { 289c7845bcaSUpinder Malhi usnic_ib_handle_inet_event(us_ibdev, event, ptr); 290c7845bcaSUpinder Malhi break; 291c7845bcaSUpinder Malhi } 292c7845bcaSUpinder Malhi } 293c7845bcaSUpinder Malhi mutex_unlock(&usnic_ib_ibdev_list_lock); 294c7845bcaSUpinder Malhi 295c7845bcaSUpinder Malhi return NOTIFY_DONE; 296c7845bcaSUpinder Malhi } 297c7845bcaSUpinder Malhi static struct notifier_block usnic_ib_inetaddr_notifier = { 298c7845bcaSUpinder Malhi .notifier_call = usnic_ib_inetaddr_event 299c7845bcaSUpinder Malhi }; 300c7845bcaSUpinder Malhi /* End of inet section*/ 301c7845bcaSUpinder Malhi 3027738613eSIra Weiny static int usnic_port_immutable(struct ib_device *ibdev, u8 port_num, 3037738613eSIra Weiny struct ib_port_immutable *immutable) 3047738613eSIra Weiny { 3057738613eSIra Weiny struct ib_port_attr attr; 3067738613eSIra Weiny int err; 3077738613eSIra Weiny 308c4550c63SOr Gerlitz immutable->core_cap_flags = RDMA_CORE_PORT_USNIC; 309c4550c63SOr Gerlitz 310c4550c63SOr Gerlitz err = ib_query_port(ibdev, port_num, &attr); 3117738613eSIra Weiny if (err) 3127738613eSIra Weiny return err; 3137738613eSIra Weiny 3147738613eSIra Weiny immutable->pkey_tbl_len = attr.pkey_tbl_len; 3157738613eSIra Weiny immutable->gid_tbl_len = attr.gid_tbl_len; 3167738613eSIra Weiny 3177738613eSIra Weiny return 0; 3187738613eSIra Weiny } 3197738613eSIra Weiny 3209abb0d1bSLeon Romanovsky static void usnic_get_dev_fw_str(struct ib_device *device, char *str) 32115453e85SIra Weiny { 32215453e85SIra Weiny struct usnic_ib_dev *us_ibdev = 32315453e85SIra Weiny container_of(device, struct usnic_ib_dev, ib_dev); 32415453e85SIra Weiny struct ethtool_drvinfo info; 32515453e85SIra Weiny 32615453e85SIra Weiny mutex_lock(&us_ibdev->usdev_lock); 32715453e85SIra Weiny us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info); 32815453e85SIra Weiny mutex_unlock(&us_ibdev->usdev_lock); 32915453e85SIra Weiny 3309abb0d1bSLeon Romanovsky snprintf(str, IB_FW_VERSION_NAME_MAX, "%s", info.fw_version); 33115453e85SIra Weiny } 33215453e85SIra Weiny 333e7610581SKamal Heib static const struct ib_device_ops usnic_dev_ops = { 334e7610581SKamal Heib .alloc_pd = usnic_ib_alloc_pd, 335e7610581SKamal Heib .alloc_ucontext = usnic_ib_alloc_ucontext, 336e7610581SKamal Heib .create_ah = usnic_ib_create_ah, 337e7610581SKamal Heib .create_cq = usnic_ib_create_cq, 338e7610581SKamal Heib .create_qp = usnic_ib_create_qp, 339e7610581SKamal Heib .dealloc_pd = usnic_ib_dealloc_pd, 340e7610581SKamal Heib .dealloc_ucontext = usnic_ib_dealloc_ucontext, 341e7610581SKamal Heib .dereg_mr = usnic_ib_dereg_mr, 342e7610581SKamal Heib .destroy_ah = usnic_ib_destroy_ah, 343e7610581SKamal Heib .destroy_cq = usnic_ib_destroy_cq, 344e7610581SKamal Heib .destroy_qp = usnic_ib_destroy_qp, 345e7610581SKamal Heib .get_dev_fw_str = usnic_get_dev_fw_str, 346e7610581SKamal Heib .get_dma_mr = usnic_ib_get_dma_mr, 347e7610581SKamal Heib .get_link_layer = usnic_ib_port_link_layer, 348e7610581SKamal Heib .get_netdev = usnic_get_netdev, 349e7610581SKamal Heib .get_port_immutable = usnic_port_immutable, 350e7610581SKamal Heib .mmap = usnic_ib_mmap, 351e7610581SKamal Heib .modify_qp = usnic_ib_modify_qp, 352e7610581SKamal Heib .poll_cq = usnic_ib_poll_cq, 353e7610581SKamal Heib .post_recv = usnic_ib_post_recv, 354e7610581SKamal Heib .post_send = usnic_ib_post_send, 355e7610581SKamal Heib .query_device = usnic_ib_query_device, 356e7610581SKamal Heib .query_gid = usnic_ib_query_gid, 357e7610581SKamal Heib .query_pkey = usnic_ib_query_pkey, 358e7610581SKamal Heib .query_port = usnic_ib_query_port, 359e7610581SKamal Heib .query_qp = usnic_ib_query_qp, 360e7610581SKamal Heib .reg_user_mr = usnic_ib_reg_mr, 361e7610581SKamal Heib .req_notify_cq = usnic_ib_req_notify_cq, 362e7610581SKamal Heib }; 363e7610581SKamal Heib 364e3cf00d0SUpinder Malhi /* Start of PF discovery section */ 365e3cf00d0SUpinder Malhi static void *usnic_ib_device_add(struct pci_dev *dev) 366e3cf00d0SUpinder Malhi { 367e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev; 368e3cf00d0SUpinder Malhi union ib_gid gid; 3695d50f400SLeon Romanovsky struct in_device *ind; 370c7845bcaSUpinder Malhi struct net_device *netdev; 371e3cf00d0SUpinder Malhi 372e3cf00d0SUpinder Malhi usnic_dbg("\n"); 373c7845bcaSUpinder Malhi netdev = pci_get_drvdata(dev); 374e3cf00d0SUpinder Malhi 375*459cc69fSLeon Romanovsky us_ibdev = ib_alloc_device(usnic_ib_dev, ib_dev); 3762c79dad8SInsu Yun if (!us_ibdev) { 377e3cf00d0SUpinder Malhi usnic_err("Device %s context alloc failed\n", 378e3cf00d0SUpinder Malhi netdev_name(pci_get_drvdata(dev))); 3792c79dad8SInsu Yun return ERR_PTR(-EFAULT); 380e3cf00d0SUpinder Malhi } 381e3cf00d0SUpinder Malhi 382e3cf00d0SUpinder Malhi us_ibdev->ufdev = usnic_fwd_dev_alloc(dev); 3832c79dad8SInsu Yun if (!us_ibdev->ufdev) { 3842c79dad8SInsu Yun usnic_err("Failed to alloc ufdev for %s\n", pci_name(dev)); 385e3cf00d0SUpinder Malhi goto err_dealloc; 386e3cf00d0SUpinder Malhi } 387e3cf00d0SUpinder Malhi 388e3cf00d0SUpinder Malhi mutex_init(&us_ibdev->usdev_lock); 389e3cf00d0SUpinder Malhi INIT_LIST_HEAD(&us_ibdev->vf_dev_list); 390e3cf00d0SUpinder Malhi INIT_LIST_HEAD(&us_ibdev->ctx_list); 391e3cf00d0SUpinder Malhi 392e3cf00d0SUpinder Malhi us_ibdev->pdev = dev; 393e3cf00d0SUpinder Malhi us_ibdev->netdev = pci_get_drvdata(dev); 394e3cf00d0SUpinder Malhi us_ibdev->ib_dev.owner = THIS_MODULE; 39561f78268SUpinder Malhi us_ibdev->ib_dev.node_type = RDMA_NODE_USNIC_UDP; 396e3cf00d0SUpinder Malhi us_ibdev->ib_dev.phys_port_cnt = USNIC_IB_PORT_CNT; 397e3cf00d0SUpinder Malhi us_ibdev->ib_dev.num_comp_vectors = USNIC_IB_NUM_COMP_VECTORS; 3986b06d52dSBart Van Assche us_ibdev->ib_dev.dev.parent = &dev->dev; 399e3cf00d0SUpinder Malhi us_ibdev->ib_dev.uverbs_abi_ver = USNIC_UVERBS_ABI_VERSION; 400e3cf00d0SUpinder Malhi 401e3cf00d0SUpinder Malhi us_ibdev->ib_dev.uverbs_cmd_mask = 402e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | 403e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | 404e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | 405e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | 406e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | 407e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_REG_MR) | 408e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_DEREG_MR) | 409e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | 410e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | 411e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | 412e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_CREATE_QP) | 413e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | 414e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_QUERY_QP) | 415e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | 416e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | 417e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) | 418e3cf00d0SUpinder Malhi (1ull << IB_USER_VERBS_CMD_OPEN_QP); 419e3cf00d0SUpinder Malhi 420e7610581SKamal Heib ib_set_device_ops(&us_ibdev->ib_dev, &usnic_dev_ops); 421e3cf00d0SUpinder Malhi 4220ede73bcSMatan Barak us_ibdev->ib_dev.driver_id = RDMA_DRIVER_USNIC; 423508a523fSParav Pandit rdma_set_device_sysfs_group(&us_ibdev->ib_dev, &usnic_attr_group); 424508a523fSParav Pandit 425ea4baf7fSParav Pandit if (ib_register_device(&us_ibdev->ib_dev, "usnic_%d")) 426e3cf00d0SUpinder Malhi goto err_fwd_dealloc; 427e3cf00d0SUpinder Malhi 4288af94ac6SUpinder Malhi usnic_fwd_set_mtu(us_ibdev->ufdev, us_ibdev->netdev->mtu); 4298af94ac6SUpinder Malhi usnic_fwd_set_mac(us_ibdev->ufdev, us_ibdev->netdev->dev_addr); 4308af94ac6SUpinder Malhi if (netif_carrier_ok(us_ibdev->netdev)) 4318af94ac6SUpinder Malhi usnic_fwd_carrier_up(us_ibdev->ufdev); 4328af94ac6SUpinder Malhi 4335d50f400SLeon Romanovsky ind = in_dev_get(netdev); 4345d50f400SLeon Romanovsky if (ind->ifa_list) 4355d50f400SLeon Romanovsky usnic_fwd_add_ipaddr(us_ibdev->ufdev, 4365d50f400SLeon Romanovsky ind->ifa_list->ifa_address); 4375d50f400SLeon Romanovsky in_dev_put(ind); 438c7845bcaSUpinder Malhi 439c7845bcaSUpinder Malhi usnic_mac_ip_to_gid(us_ibdev->netdev->perm_addr, 440c7845bcaSUpinder Malhi us_ibdev->ufdev->inaddr, &gid.raw[0]); 441e3cf00d0SUpinder Malhi memcpy(&us_ibdev->ib_dev.node_guid, &gid.global.interface_id, 442e3cf00d0SUpinder Malhi sizeof(gid.global.interface_id)); 443e3cf00d0SUpinder Malhi kref_init(&us_ibdev->vf_cnt); 444e3cf00d0SUpinder Malhi 445e3cf00d0SUpinder Malhi usnic_info("Added ibdev: %s netdev: %s with mac %pM Link: %u MTU: %u\n", 4469de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev), 4479de69861SJason Gunthorpe netdev_name(us_ibdev->netdev), us_ibdev->ufdev->mac, 4489de69861SJason Gunthorpe us_ibdev->ufdev->link_up, us_ibdev->ufdev->mtu); 449e3cf00d0SUpinder Malhi return us_ibdev; 450e3cf00d0SUpinder Malhi 451e3cf00d0SUpinder Malhi err_fwd_dealloc: 452e3cf00d0SUpinder Malhi usnic_fwd_dev_free(us_ibdev->ufdev); 453e3cf00d0SUpinder Malhi err_dealloc: 454e3cf00d0SUpinder Malhi usnic_err("failed -- deallocing device\n"); 455e3cf00d0SUpinder Malhi ib_dealloc_device(&us_ibdev->ib_dev); 456e3cf00d0SUpinder Malhi return NULL; 457e3cf00d0SUpinder Malhi } 458e3cf00d0SUpinder Malhi 459e3cf00d0SUpinder Malhi static void usnic_ib_device_remove(struct usnic_ib_dev *us_ibdev) 460e3cf00d0SUpinder Malhi { 4619de69861SJason Gunthorpe usnic_info("Unregistering %s\n", dev_name(&us_ibdev->ib_dev.dev)); 462e3cf00d0SUpinder Malhi usnic_ib_sysfs_unregister_usdev(us_ibdev); 463e3cf00d0SUpinder Malhi usnic_fwd_dev_free(us_ibdev->ufdev); 464e3cf00d0SUpinder Malhi ib_unregister_device(&us_ibdev->ib_dev); 465e3cf00d0SUpinder Malhi ib_dealloc_device(&us_ibdev->ib_dev); 466e3cf00d0SUpinder Malhi } 467e3cf00d0SUpinder Malhi 468e3cf00d0SUpinder Malhi static void usnic_ib_undiscover_pf(struct kref *kref) 469e3cf00d0SUpinder Malhi { 470e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev, *tmp; 471e3cf00d0SUpinder Malhi struct pci_dev *dev; 472e3cf00d0SUpinder Malhi bool found = false; 473e3cf00d0SUpinder Malhi 474e3cf00d0SUpinder Malhi dev = container_of(kref, struct usnic_ib_dev, vf_cnt)->pdev; 475e3cf00d0SUpinder Malhi mutex_lock(&usnic_ib_ibdev_list_lock); 476e3cf00d0SUpinder Malhi list_for_each_entry_safe(us_ibdev, tmp, 477e3cf00d0SUpinder Malhi &usnic_ib_ibdev_list, ib_dev_link) { 478e3cf00d0SUpinder Malhi if (us_ibdev->pdev == dev) { 479e3cf00d0SUpinder Malhi list_del(&us_ibdev->ib_dev_link); 480e3cf00d0SUpinder Malhi usnic_ib_device_remove(us_ibdev); 481e3cf00d0SUpinder Malhi found = true; 482e3cf00d0SUpinder Malhi break; 483e3cf00d0SUpinder Malhi } 484e3cf00d0SUpinder Malhi } 485e3cf00d0SUpinder Malhi 486e3cf00d0SUpinder Malhi WARN(!found, "Failed to remove PF %s\n", pci_name(dev)); 487e3cf00d0SUpinder Malhi 488e3cf00d0SUpinder Malhi mutex_unlock(&usnic_ib_ibdev_list_lock); 489e3cf00d0SUpinder Malhi } 490e3cf00d0SUpinder Malhi 491e3cf00d0SUpinder Malhi static struct usnic_ib_dev *usnic_ib_discover_pf(struct usnic_vnic *vnic) 492e3cf00d0SUpinder Malhi { 493e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev; 494e3cf00d0SUpinder Malhi struct pci_dev *parent_pci, *vf_pci; 495e3cf00d0SUpinder Malhi int err; 496e3cf00d0SUpinder Malhi 497e3cf00d0SUpinder Malhi vf_pci = usnic_vnic_get_pdev(vnic); 498e3cf00d0SUpinder Malhi parent_pci = pci_physfn(vf_pci); 499e3cf00d0SUpinder Malhi 500e3cf00d0SUpinder Malhi BUG_ON(!parent_pci); 501e3cf00d0SUpinder Malhi 502e3cf00d0SUpinder Malhi mutex_lock(&usnic_ib_ibdev_list_lock); 503e3cf00d0SUpinder Malhi list_for_each_entry(us_ibdev, &usnic_ib_ibdev_list, ib_dev_link) { 504e3cf00d0SUpinder Malhi if (us_ibdev->pdev == parent_pci) { 505e3cf00d0SUpinder Malhi kref_get(&us_ibdev->vf_cnt); 506e3cf00d0SUpinder Malhi goto out; 507e3cf00d0SUpinder Malhi } 508e3cf00d0SUpinder Malhi } 509e3cf00d0SUpinder Malhi 510e3cf00d0SUpinder Malhi us_ibdev = usnic_ib_device_add(parent_pci); 511e3cf00d0SUpinder Malhi if (IS_ERR_OR_NULL(us_ibdev)) { 5126a54d9f9SUpinder Malhi us_ibdev = us_ibdev ? us_ibdev : ERR_PTR(-EFAULT); 513e3cf00d0SUpinder Malhi goto out; 514e3cf00d0SUpinder Malhi } 515e3cf00d0SUpinder Malhi 516e3cf00d0SUpinder Malhi err = usnic_ib_sysfs_register_usdev(us_ibdev); 517e3cf00d0SUpinder Malhi if (err) { 518e3cf00d0SUpinder Malhi usnic_ib_device_remove(us_ibdev); 519e3cf00d0SUpinder Malhi us_ibdev = ERR_PTR(err); 520e3cf00d0SUpinder Malhi goto out; 521e3cf00d0SUpinder Malhi } 522e3cf00d0SUpinder Malhi 523e3cf00d0SUpinder Malhi list_add(&us_ibdev->ib_dev_link, &usnic_ib_ibdev_list); 524e3cf00d0SUpinder Malhi out: 525e3cf00d0SUpinder Malhi mutex_unlock(&usnic_ib_ibdev_list_lock); 526e3cf00d0SUpinder Malhi return us_ibdev; 527e3cf00d0SUpinder Malhi } 528e3cf00d0SUpinder Malhi /* End of PF discovery section */ 529e3cf00d0SUpinder Malhi 530e3cf00d0SUpinder Malhi /* Start of PCI section */ 531e3cf00d0SUpinder Malhi 5329baa3c34SBenoit Taine static const struct pci_device_id usnic_ib_pci_ids[] = { 533e3cf00d0SUpinder Malhi {PCI_DEVICE(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_USPACE_NIC)}, 534e3cf00d0SUpinder Malhi {0,} 535e3cf00d0SUpinder Malhi }; 536e3cf00d0SUpinder Malhi 537e3cf00d0SUpinder Malhi static int usnic_ib_pci_probe(struct pci_dev *pdev, 538e3cf00d0SUpinder Malhi const struct pci_device_id *id) 539e3cf00d0SUpinder Malhi { 540e3cf00d0SUpinder Malhi int err; 541e3cf00d0SUpinder Malhi struct usnic_ib_dev *pf; 542e3cf00d0SUpinder Malhi struct usnic_ib_vf *vf; 543e3cf00d0SUpinder Malhi enum usnic_vnic_res_type res_type; 544e3cf00d0SUpinder Malhi 545e3cf00d0SUpinder Malhi vf = kzalloc(sizeof(*vf), GFP_KERNEL); 546e3cf00d0SUpinder Malhi if (!vf) 547e3cf00d0SUpinder Malhi return -ENOMEM; 548e3cf00d0SUpinder Malhi 549e3cf00d0SUpinder Malhi err = pci_enable_device(pdev); 550e3cf00d0SUpinder Malhi if (err) { 551e3cf00d0SUpinder Malhi usnic_err("Failed to enable %s with err %d\n", 552e3cf00d0SUpinder Malhi pci_name(pdev), err); 553e3cf00d0SUpinder Malhi goto out_clean_vf; 554e3cf00d0SUpinder Malhi } 555e3cf00d0SUpinder Malhi 556e3cf00d0SUpinder Malhi err = pci_request_regions(pdev, DRV_NAME); 557e3cf00d0SUpinder Malhi if (err) { 558e3cf00d0SUpinder Malhi usnic_err("Failed to request region for %s with err %d\n", 559e3cf00d0SUpinder Malhi pci_name(pdev), err); 560e3cf00d0SUpinder Malhi goto out_disable_device; 561e3cf00d0SUpinder Malhi } 562e3cf00d0SUpinder Malhi 563e3cf00d0SUpinder Malhi pci_set_master(pdev); 564e3cf00d0SUpinder Malhi pci_set_drvdata(pdev, vf); 565e3cf00d0SUpinder Malhi 566e3cf00d0SUpinder Malhi vf->vnic = usnic_vnic_alloc(pdev); 567e3cf00d0SUpinder Malhi if (IS_ERR_OR_NULL(vf->vnic)) { 5686a54d9f9SUpinder Malhi err = vf->vnic ? PTR_ERR(vf->vnic) : -ENOMEM; 569e3cf00d0SUpinder Malhi usnic_err("Failed to alloc vnic for %s with err %d\n", 570e3cf00d0SUpinder Malhi pci_name(pdev), err); 571e3cf00d0SUpinder Malhi goto out_release_regions; 572e3cf00d0SUpinder Malhi } 573e3cf00d0SUpinder Malhi 574e3cf00d0SUpinder Malhi pf = usnic_ib_discover_pf(vf->vnic); 575e3cf00d0SUpinder Malhi if (IS_ERR_OR_NULL(pf)) { 576e3cf00d0SUpinder Malhi usnic_err("Failed to discover pf of vnic %s with err%ld\n", 577e3cf00d0SUpinder Malhi pci_name(pdev), PTR_ERR(pf)); 5786a54d9f9SUpinder Malhi err = pf ? PTR_ERR(pf) : -EFAULT; 579e3cf00d0SUpinder Malhi goto out_clean_vnic; 580e3cf00d0SUpinder Malhi } 581e3cf00d0SUpinder Malhi 582e3cf00d0SUpinder Malhi vf->pf = pf; 583e3cf00d0SUpinder Malhi spin_lock_init(&vf->lock); 584e3cf00d0SUpinder Malhi mutex_lock(&pf->usdev_lock); 585e3cf00d0SUpinder Malhi list_add_tail(&vf->link, &pf->vf_dev_list); 586e3cf00d0SUpinder Malhi /* 587e3cf00d0SUpinder Malhi * Save max settings (will be same for each VF, easier to re-write than 588e3cf00d0SUpinder Malhi * to say "if (!set) { set_values(); set=1; } 589e3cf00d0SUpinder Malhi */ 590e3cf00d0SUpinder Malhi for (res_type = USNIC_VNIC_RES_TYPE_EOL+1; 591e3cf00d0SUpinder Malhi res_type < USNIC_VNIC_RES_TYPE_MAX; 592e3cf00d0SUpinder Malhi res_type++) { 593e3cf00d0SUpinder Malhi pf->vf_res_cnt[res_type] = usnic_vnic_res_cnt(vf->vnic, 594e3cf00d0SUpinder Malhi res_type); 595e3cf00d0SUpinder Malhi } 596e3cf00d0SUpinder Malhi 597e3cf00d0SUpinder Malhi mutex_unlock(&pf->usdev_lock); 598e3cf00d0SUpinder Malhi 599e3cf00d0SUpinder Malhi usnic_info("Registering usnic VF %s into PF %s\n", pci_name(pdev), 6009de69861SJason Gunthorpe dev_name(&pf->ib_dev.dev)); 601e3cf00d0SUpinder Malhi usnic_ib_log_vf(vf); 602e3cf00d0SUpinder Malhi return 0; 603e3cf00d0SUpinder Malhi 604e3cf00d0SUpinder Malhi out_clean_vnic: 605e3cf00d0SUpinder Malhi usnic_vnic_free(vf->vnic); 606e3cf00d0SUpinder Malhi out_release_regions: 607e3cf00d0SUpinder Malhi pci_set_drvdata(pdev, NULL); 608e3cf00d0SUpinder Malhi pci_clear_master(pdev); 609e3cf00d0SUpinder Malhi pci_release_regions(pdev); 610e3cf00d0SUpinder Malhi out_disable_device: 611e3cf00d0SUpinder Malhi pci_disable_device(pdev); 612e3cf00d0SUpinder Malhi out_clean_vf: 613e3cf00d0SUpinder Malhi kfree(vf); 614e3cf00d0SUpinder Malhi return err; 615e3cf00d0SUpinder Malhi } 616e3cf00d0SUpinder Malhi 617e3cf00d0SUpinder Malhi static void usnic_ib_pci_remove(struct pci_dev *pdev) 618e3cf00d0SUpinder Malhi { 619e3cf00d0SUpinder Malhi struct usnic_ib_vf *vf = pci_get_drvdata(pdev); 620e3cf00d0SUpinder Malhi struct usnic_ib_dev *pf = vf->pf; 621e3cf00d0SUpinder Malhi 622e3cf00d0SUpinder Malhi mutex_lock(&pf->usdev_lock); 623e3cf00d0SUpinder Malhi list_del(&vf->link); 624e3cf00d0SUpinder Malhi mutex_unlock(&pf->usdev_lock); 625e3cf00d0SUpinder Malhi 626e3cf00d0SUpinder Malhi kref_put(&pf->vf_cnt, usnic_ib_undiscover_pf); 627e3cf00d0SUpinder Malhi usnic_vnic_free(vf->vnic); 628e3cf00d0SUpinder Malhi pci_set_drvdata(pdev, NULL); 629e3cf00d0SUpinder Malhi pci_clear_master(pdev); 630e3cf00d0SUpinder Malhi pci_release_regions(pdev); 631e3cf00d0SUpinder Malhi pci_disable_device(pdev); 632e3cf00d0SUpinder Malhi kfree(vf); 633e3cf00d0SUpinder Malhi 634e3cf00d0SUpinder Malhi usnic_info("Removed VF %s\n", pci_name(pdev)); 635e3cf00d0SUpinder Malhi } 636e3cf00d0SUpinder Malhi 637e3cf00d0SUpinder Malhi /* PCI driver entry points */ 638e3cf00d0SUpinder Malhi static struct pci_driver usnic_ib_pci_driver = { 639e3cf00d0SUpinder Malhi .name = DRV_NAME, 640e3cf00d0SUpinder Malhi .id_table = usnic_ib_pci_ids, 641e3cf00d0SUpinder Malhi .probe = usnic_ib_pci_probe, 642e3cf00d0SUpinder Malhi .remove = usnic_ib_pci_remove, 643e3cf00d0SUpinder Malhi }; 644e3cf00d0SUpinder Malhi /* End of PCI section */ 645e3cf00d0SUpinder Malhi 646e3cf00d0SUpinder Malhi /* Start of module section */ 647e3cf00d0SUpinder Malhi static int __init usnic_ib_init(void) 648e3cf00d0SUpinder Malhi { 649e3cf00d0SUpinder Malhi int err; 650e3cf00d0SUpinder Malhi 651e3cf00d0SUpinder Malhi printk_once(KERN_INFO "%s", usnic_version); 652e3cf00d0SUpinder Malhi 653e3cf00d0SUpinder Malhi err = usnic_uiom_init(DRV_NAME); 654e3cf00d0SUpinder Malhi if (err) { 655901018f2SColin Ian King usnic_err("Unable to initialize umem with err %d\n", err); 656e3cf00d0SUpinder Malhi return err; 657e3cf00d0SUpinder Malhi } 658e3cf00d0SUpinder Malhi 65986cd747cSChristophe Jaillet err = pci_register_driver(&usnic_ib_pci_driver); 66086cd747cSChristophe Jaillet if (err) { 661e3cf00d0SUpinder Malhi usnic_err("Unable to register with PCI\n"); 662e3cf00d0SUpinder Malhi goto out_umem_fini; 663e3cf00d0SUpinder Malhi } 664e3cf00d0SUpinder Malhi 665e3cf00d0SUpinder Malhi err = register_netdevice_notifier(&usnic_ib_netdevice_notifier); 666e3cf00d0SUpinder Malhi if (err) { 667e3cf00d0SUpinder Malhi usnic_err("Failed to register netdev notifier\n"); 668e3cf00d0SUpinder Malhi goto out_pci_unreg; 669e3cf00d0SUpinder Malhi } 670e3cf00d0SUpinder Malhi 671c7845bcaSUpinder Malhi err = register_inetaddr_notifier(&usnic_ib_inetaddr_notifier); 672c7845bcaSUpinder Malhi if (err) { 673c7845bcaSUpinder Malhi usnic_err("Failed to register inet addr notifier\n"); 674c7845bcaSUpinder Malhi goto out_unreg_netdev_notifier; 675c7845bcaSUpinder Malhi } 676c7845bcaSUpinder Malhi 677e3cf00d0SUpinder Malhi err = usnic_transport_init(); 678e3cf00d0SUpinder Malhi if (err) { 679e3cf00d0SUpinder Malhi usnic_err("Failed to initialize transport\n"); 680c7845bcaSUpinder Malhi goto out_unreg_inetaddr_notifier; 681e3cf00d0SUpinder Malhi } 682e3cf00d0SUpinder Malhi 683e3cf00d0SUpinder Malhi usnic_debugfs_init(); 684e3cf00d0SUpinder Malhi 685e3cf00d0SUpinder Malhi return 0; 686e3cf00d0SUpinder Malhi 687c7845bcaSUpinder Malhi out_unreg_inetaddr_notifier: 688c7845bcaSUpinder Malhi unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier); 689e3cf00d0SUpinder Malhi out_unreg_netdev_notifier: 690e3cf00d0SUpinder Malhi unregister_netdevice_notifier(&usnic_ib_netdevice_notifier); 691e3cf00d0SUpinder Malhi out_pci_unreg: 692e3cf00d0SUpinder Malhi pci_unregister_driver(&usnic_ib_pci_driver); 693e3cf00d0SUpinder Malhi out_umem_fini: 694e3cf00d0SUpinder Malhi usnic_uiom_fini(); 695e3cf00d0SUpinder Malhi 696e3cf00d0SUpinder Malhi return err; 697e3cf00d0SUpinder Malhi } 698e3cf00d0SUpinder Malhi 699e3cf00d0SUpinder Malhi static void __exit usnic_ib_destroy(void) 700e3cf00d0SUpinder Malhi { 701e3cf00d0SUpinder Malhi usnic_dbg("\n"); 702e3cf00d0SUpinder Malhi usnic_debugfs_exit(); 703e3cf00d0SUpinder Malhi usnic_transport_fini(); 704c7845bcaSUpinder Malhi unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier); 705e3cf00d0SUpinder Malhi unregister_netdevice_notifier(&usnic_ib_netdevice_notifier); 706e3cf00d0SUpinder Malhi pci_unregister_driver(&usnic_ib_pci_driver); 707e3cf00d0SUpinder Malhi usnic_uiom_fini(); 708e3cf00d0SUpinder Malhi } 709e3cf00d0SUpinder Malhi 710e3cf00d0SUpinder Malhi MODULE_DESCRIPTION("Cisco VIC (usNIC) Verbs Driver"); 711e3cf00d0SUpinder Malhi MODULE_AUTHOR("Upinder Malhi <umalhi@cisco.com>"); 712e3cf00d0SUpinder Malhi MODULE_LICENSE("Dual BSD/GPL"); 713e3cf00d0SUpinder Malhi module_param(usnic_log_lvl, uint, S_IRUGO | S_IWUSR); 714e3cf00d0SUpinder Malhi module_param(usnic_ib_share_vf, uint, S_IRUGO | S_IWUSR); 715e3cf00d0SUpinder Malhi MODULE_PARM_DESC(usnic_log_lvl, " Off=0, Err=1, Info=2, Debug=3"); 716e3cf00d0SUpinder Malhi MODULE_PARM_DESC(usnic_ib_share_vf, "Off=0, On=1 VF sharing amongst QPs"); 717e3cf00d0SUpinder Malhi MODULE_DEVICE_TABLE(pci, usnic_ib_pci_ids); 718e3cf00d0SUpinder Malhi 719e3cf00d0SUpinder Malhi module_init(usnic_ib_init); 720e3cf00d0SUpinder Malhi module_exit(usnic_ib_destroy); 721e3cf00d0SUpinder Malhi /* End of module section */ 722