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 { 922ac5a6d3SArnd Bergmann char *buf = kzalloc(1000, GFP_KERNEL); 932ac5a6d3SArnd Bergmann 942ac5a6d3SArnd Bergmann if (!buf) 952ac5a6d3SArnd Bergmann return; 962ac5a6d3SArnd Bergmann 972ac5a6d3SArnd Bergmann usnic_ib_dump_vf(vf, buf, 1000); 98e3cf00d0SUpinder Malhi usnic_dbg("%s\n", buf); 992ac5a6d3SArnd Bergmann 1002ac5a6d3SArnd Bergmann kfree(buf); 101e3cf00d0SUpinder Malhi } 102e3cf00d0SUpinder Malhi 103e3cf00d0SUpinder Malhi /* Start of netdev section */ 104e3cf00d0SUpinder Malhi static void usnic_ib_qp_grp_modify_active_to_err(struct usnic_ib_dev *us_ibdev) 105e3cf00d0SUpinder Malhi { 106e3cf00d0SUpinder Malhi struct usnic_ib_ucontext *ctx; 107e3cf00d0SUpinder Malhi struct usnic_ib_qp_grp *qp_grp; 108e3cf00d0SUpinder Malhi enum ib_qp_state cur_state; 109e3cf00d0SUpinder Malhi int status; 110e3cf00d0SUpinder Malhi 111e3cf00d0SUpinder Malhi BUG_ON(!mutex_is_locked(&us_ibdev->usdev_lock)); 112e3cf00d0SUpinder Malhi 113e3cf00d0SUpinder Malhi list_for_each_entry(ctx, &us_ibdev->ctx_list, link) { 114e3cf00d0SUpinder Malhi list_for_each_entry(qp_grp, &ctx->qp_grp_list, link) { 115e3cf00d0SUpinder Malhi cur_state = qp_grp->state; 116e3cf00d0SUpinder Malhi if (cur_state == IB_QPS_INIT || 117e3cf00d0SUpinder Malhi cur_state == IB_QPS_RTR || 118e3cf00d0SUpinder Malhi cur_state == IB_QPS_RTS) { 119e3cf00d0SUpinder Malhi status = usnic_ib_qp_grp_modify(qp_grp, 120e3cf00d0SUpinder Malhi IB_QPS_ERR, 121e3cf00d0SUpinder Malhi NULL); 122e3cf00d0SUpinder Malhi if (status) { 123dfd022a9SColin Ian King usnic_err("Failed to transition qp grp %u from %s to %s\n", 124e3cf00d0SUpinder Malhi qp_grp->grp_id, 125e3cf00d0SUpinder Malhi usnic_ib_qp_grp_state_to_string 126e3cf00d0SUpinder Malhi (cur_state), 127e3cf00d0SUpinder Malhi usnic_ib_qp_grp_state_to_string 128e3cf00d0SUpinder Malhi (IB_QPS_ERR)); 129e3cf00d0SUpinder Malhi } 130e3cf00d0SUpinder Malhi } 131e3cf00d0SUpinder Malhi } 132e3cf00d0SUpinder Malhi } 133e3cf00d0SUpinder Malhi } 134e3cf00d0SUpinder Malhi 135e3cf00d0SUpinder Malhi static void usnic_ib_handle_usdev_event(struct usnic_ib_dev *us_ibdev, 136e3cf00d0SUpinder Malhi unsigned long event) 137e3cf00d0SUpinder Malhi { 138e3cf00d0SUpinder Malhi struct net_device *netdev; 139e3cf00d0SUpinder Malhi struct ib_event ib_event; 140e3cf00d0SUpinder Malhi 141e3cf00d0SUpinder Malhi memset(&ib_event, 0, sizeof(ib_event)); 142e3cf00d0SUpinder Malhi 143e3cf00d0SUpinder Malhi mutex_lock(&us_ibdev->usdev_lock); 144e3cf00d0SUpinder Malhi netdev = us_ibdev->netdev; 145e3cf00d0SUpinder Malhi switch (event) { 146e3cf00d0SUpinder Malhi case NETDEV_REBOOT: 1479de69861SJason Gunthorpe usnic_info("PF Reset on %s\n", dev_name(&us_ibdev->ib_dev.dev)); 148e3cf00d0SUpinder Malhi usnic_ib_qp_grp_modify_active_to_err(us_ibdev); 149e3cf00d0SUpinder Malhi ib_event.event = IB_EVENT_PORT_ERR; 150e3cf00d0SUpinder Malhi ib_event.device = &us_ibdev->ib_dev; 151e3cf00d0SUpinder Malhi ib_event.element.port_num = 1; 152e3cf00d0SUpinder Malhi ib_dispatch_event(&ib_event); 153e3cf00d0SUpinder Malhi break; 154e3cf00d0SUpinder Malhi case NETDEV_UP: 155e3cf00d0SUpinder Malhi case NETDEV_DOWN: 156e3cf00d0SUpinder Malhi case NETDEV_CHANGE: 1578af94ac6SUpinder Malhi if (!us_ibdev->ufdev->link_up && 1588af94ac6SUpinder Malhi netif_carrier_ok(netdev)) { 1598af94ac6SUpinder Malhi usnic_fwd_carrier_up(us_ibdev->ufdev); 1609de69861SJason Gunthorpe usnic_info("Link UP on %s\n", 1619de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 162e3cf00d0SUpinder Malhi ib_event.event = IB_EVENT_PORT_ACTIVE; 163e3cf00d0SUpinder Malhi ib_event.device = &us_ibdev->ib_dev; 164e3cf00d0SUpinder Malhi ib_event.element.port_num = 1; 165e3cf00d0SUpinder Malhi ib_dispatch_event(&ib_event); 1668af94ac6SUpinder Malhi } else if (us_ibdev->ufdev->link_up && 1678af94ac6SUpinder Malhi !netif_carrier_ok(netdev)) { 1688af94ac6SUpinder Malhi usnic_fwd_carrier_down(us_ibdev->ufdev); 1699de69861SJason Gunthorpe usnic_info("Link DOWN on %s\n", 1709de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 171e3cf00d0SUpinder Malhi usnic_ib_qp_grp_modify_active_to_err(us_ibdev); 172e3cf00d0SUpinder Malhi ib_event.event = IB_EVENT_PORT_ERR; 173e3cf00d0SUpinder Malhi ib_event.device = &us_ibdev->ib_dev; 174e3cf00d0SUpinder Malhi ib_event.element.port_num = 1; 175e3cf00d0SUpinder Malhi ib_dispatch_event(&ib_event); 176e3cf00d0SUpinder Malhi } else { 177c30392abSRoland Dreier usnic_dbg("Ignoring %s on %s\n", 1783e0c2dbfSKirill Tkhai netdev_cmd_to_name(event), 1799de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 180e3cf00d0SUpinder Malhi } 181e3cf00d0SUpinder Malhi break; 182e3cf00d0SUpinder Malhi case NETDEV_CHANGEADDR: 1838af94ac6SUpinder Malhi if (!memcmp(us_ibdev->ufdev->mac, netdev->dev_addr, 1848af94ac6SUpinder Malhi sizeof(us_ibdev->ufdev->mac))) { 185c30392abSRoland Dreier usnic_dbg("Ignoring addr change on %s\n", 1869de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 187e3cf00d0SUpinder Malhi } else { 188e3cf00d0SUpinder Malhi usnic_info(" %s old mac: %pM new mac: %pM\n", 1899de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev), 1908af94ac6SUpinder Malhi us_ibdev->ufdev->mac, 191e3cf00d0SUpinder Malhi netdev->dev_addr); 1928af94ac6SUpinder Malhi usnic_fwd_set_mac(us_ibdev->ufdev, netdev->dev_addr); 193e3cf00d0SUpinder Malhi usnic_ib_qp_grp_modify_active_to_err(us_ibdev); 194e3cf00d0SUpinder Malhi ib_event.event = IB_EVENT_GID_CHANGE; 195e3cf00d0SUpinder Malhi ib_event.device = &us_ibdev->ib_dev; 196e3cf00d0SUpinder Malhi ib_event.element.port_num = 1; 197e3cf00d0SUpinder Malhi ib_dispatch_event(&ib_event); 198e3cf00d0SUpinder Malhi } 199e3cf00d0SUpinder Malhi 200e3cf00d0SUpinder Malhi break; 201e3cf00d0SUpinder Malhi case NETDEV_CHANGEMTU: 2028af94ac6SUpinder Malhi if (us_ibdev->ufdev->mtu != netdev->mtu) { 203e3cf00d0SUpinder Malhi usnic_info("MTU Change on %s old: %u new: %u\n", 2049de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev), 2058af94ac6SUpinder Malhi us_ibdev->ufdev->mtu, netdev->mtu); 2068af94ac6SUpinder Malhi usnic_fwd_set_mtu(us_ibdev->ufdev, netdev->mtu); 207e3cf00d0SUpinder Malhi usnic_ib_qp_grp_modify_active_to_err(us_ibdev); 208e3cf00d0SUpinder Malhi } else { 209e3cf00d0SUpinder Malhi usnic_dbg("Ignoring MTU change on %s\n", 2109de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 211e3cf00d0SUpinder Malhi } 212e3cf00d0SUpinder Malhi break; 213e3cf00d0SUpinder Malhi default: 214c30392abSRoland Dreier usnic_dbg("Ignoring event %s on %s", 2153e0c2dbfSKirill Tkhai netdev_cmd_to_name(event), 2169de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 217e3cf00d0SUpinder Malhi } 218e3cf00d0SUpinder Malhi mutex_unlock(&us_ibdev->usdev_lock); 219e3cf00d0SUpinder Malhi } 220e3cf00d0SUpinder Malhi 221e3cf00d0SUpinder Malhi static int usnic_ib_netdevice_event(struct notifier_block *notifier, 222e3cf00d0SUpinder Malhi unsigned long event, void *ptr) 223e3cf00d0SUpinder Malhi { 224e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev; 2255bb3c1e9SParvi Kaustubhi struct ib_device *ibdev; 226e3cf00d0SUpinder Malhi 227e3cf00d0SUpinder Malhi struct net_device *netdev = netdev_notifier_info_to_dev(ptr); 228e3cf00d0SUpinder Malhi 2295bb3c1e9SParvi Kaustubhi ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_USNIC); 2305bb3c1e9SParvi Kaustubhi if (!ibdev) 2315bb3c1e9SParvi Kaustubhi return NOTIFY_DONE; 232e3cf00d0SUpinder Malhi 2335bb3c1e9SParvi Kaustubhi us_ibdev = container_of(ibdev, struct usnic_ib_dev, ib_dev); 2345bb3c1e9SParvi Kaustubhi usnic_ib_handle_usdev_event(us_ibdev, event); 2355bb3c1e9SParvi Kaustubhi ib_device_put(ibdev); 236e3cf00d0SUpinder Malhi return NOTIFY_DONE; 237e3cf00d0SUpinder Malhi } 238e3cf00d0SUpinder Malhi 239e3cf00d0SUpinder Malhi static struct notifier_block usnic_ib_netdevice_notifier = { 240e3cf00d0SUpinder Malhi .notifier_call = usnic_ib_netdevice_event 241e3cf00d0SUpinder Malhi }; 242e3cf00d0SUpinder Malhi /* End of netdev section */ 243e3cf00d0SUpinder Malhi 244c7845bcaSUpinder Malhi /* Start of inet section */ 245c7845bcaSUpinder Malhi static int usnic_ib_handle_inet_event(struct usnic_ib_dev *us_ibdev, 246c7845bcaSUpinder Malhi unsigned long event, void *ptr) 247c7845bcaSUpinder Malhi { 248c7845bcaSUpinder Malhi struct in_ifaddr *ifa = ptr; 249c7845bcaSUpinder Malhi struct ib_event ib_event; 250c7845bcaSUpinder Malhi 251c7845bcaSUpinder Malhi mutex_lock(&us_ibdev->usdev_lock); 252c7845bcaSUpinder Malhi 253c7845bcaSUpinder Malhi switch (event) { 254c7845bcaSUpinder Malhi case NETDEV_DOWN: 255c7845bcaSUpinder Malhi usnic_info("%s via ip notifiers", 2563e0c2dbfSKirill Tkhai netdev_cmd_to_name(event)); 257c7845bcaSUpinder Malhi usnic_fwd_del_ipaddr(us_ibdev->ufdev); 258c7845bcaSUpinder Malhi usnic_ib_qp_grp_modify_active_to_err(us_ibdev); 259c7845bcaSUpinder Malhi ib_event.event = IB_EVENT_GID_CHANGE; 260c7845bcaSUpinder Malhi ib_event.device = &us_ibdev->ib_dev; 261c7845bcaSUpinder Malhi ib_event.element.port_num = 1; 262c7845bcaSUpinder Malhi ib_dispatch_event(&ib_event); 263c7845bcaSUpinder Malhi break; 264c7845bcaSUpinder Malhi case NETDEV_UP: 265c7845bcaSUpinder Malhi usnic_fwd_add_ipaddr(us_ibdev->ufdev, ifa->ifa_address); 266c7845bcaSUpinder Malhi usnic_info("%s via ip notifiers: ip %pI4", 2673e0c2dbfSKirill Tkhai netdev_cmd_to_name(event), 268c7845bcaSUpinder Malhi &us_ibdev->ufdev->inaddr); 269c7845bcaSUpinder Malhi ib_event.event = IB_EVENT_GID_CHANGE; 270c7845bcaSUpinder Malhi ib_event.device = &us_ibdev->ib_dev; 271c7845bcaSUpinder Malhi ib_event.element.port_num = 1; 272c7845bcaSUpinder Malhi ib_dispatch_event(&ib_event); 273c7845bcaSUpinder Malhi break; 274c7845bcaSUpinder Malhi default: 275c30392abSRoland Dreier usnic_info("Ignoring event %s on %s", 2763e0c2dbfSKirill Tkhai netdev_cmd_to_name(event), 2779de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 278c7845bcaSUpinder Malhi } 279c7845bcaSUpinder Malhi mutex_unlock(&us_ibdev->usdev_lock); 280c7845bcaSUpinder Malhi 281c7845bcaSUpinder Malhi return NOTIFY_DONE; 282c7845bcaSUpinder Malhi } 283c7845bcaSUpinder Malhi 284c7845bcaSUpinder Malhi static int usnic_ib_inetaddr_event(struct notifier_block *notifier, 285c7845bcaSUpinder Malhi unsigned long event, void *ptr) 286c7845bcaSUpinder Malhi { 287c7845bcaSUpinder Malhi struct usnic_ib_dev *us_ibdev; 288c7845bcaSUpinder Malhi struct in_ifaddr *ifa = ptr; 289c7845bcaSUpinder Malhi struct net_device *netdev = ifa->ifa_dev->dev; 2905bb3c1e9SParvi Kaustubhi struct ib_device *ibdev; 291c7845bcaSUpinder Malhi 2925bb3c1e9SParvi Kaustubhi ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_USNIC); 2935bb3c1e9SParvi Kaustubhi if (!ibdev) 2945bb3c1e9SParvi Kaustubhi return NOTIFY_DONE; 2955bb3c1e9SParvi Kaustubhi 2965bb3c1e9SParvi Kaustubhi us_ibdev = container_of(ibdev, struct usnic_ib_dev, ib_dev); 297c7845bcaSUpinder Malhi usnic_ib_handle_inet_event(us_ibdev, event, ptr); 2985bb3c1e9SParvi Kaustubhi ib_device_put(ibdev); 299c7845bcaSUpinder Malhi return NOTIFY_DONE; 300c7845bcaSUpinder Malhi } 301c7845bcaSUpinder Malhi static struct notifier_block usnic_ib_inetaddr_notifier = { 302c7845bcaSUpinder Malhi .notifier_call = usnic_ib_inetaddr_event 303c7845bcaSUpinder Malhi }; 304c7845bcaSUpinder Malhi /* End of inet section*/ 305c7845bcaSUpinder Malhi 3067738613eSIra Weiny static int usnic_port_immutable(struct ib_device *ibdev, u8 port_num, 3077738613eSIra Weiny struct ib_port_immutable *immutable) 3087738613eSIra Weiny { 3097738613eSIra Weiny struct ib_port_attr attr; 3107738613eSIra Weiny int err; 3117738613eSIra Weiny 312c4550c63SOr Gerlitz immutable->core_cap_flags = RDMA_CORE_PORT_USNIC; 313c4550c63SOr Gerlitz 314c4550c63SOr Gerlitz err = ib_query_port(ibdev, port_num, &attr); 3157738613eSIra Weiny if (err) 3167738613eSIra Weiny return err; 3177738613eSIra Weiny 3187738613eSIra Weiny immutable->gid_tbl_len = attr.gid_tbl_len; 3197738613eSIra Weiny 3207738613eSIra Weiny return 0; 3217738613eSIra Weiny } 3227738613eSIra Weiny 3239abb0d1bSLeon Romanovsky static void usnic_get_dev_fw_str(struct ib_device *device, char *str) 32415453e85SIra Weiny { 32515453e85SIra Weiny struct usnic_ib_dev *us_ibdev = 32615453e85SIra Weiny container_of(device, struct usnic_ib_dev, ib_dev); 32715453e85SIra Weiny struct ethtool_drvinfo info; 32815453e85SIra Weiny 32915453e85SIra Weiny mutex_lock(&us_ibdev->usdev_lock); 33015453e85SIra Weiny us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info); 33115453e85SIra Weiny mutex_unlock(&us_ibdev->usdev_lock); 33215453e85SIra Weiny 3339abb0d1bSLeon Romanovsky snprintf(str, IB_FW_VERSION_NAME_MAX, "%s", info.fw_version); 33415453e85SIra Weiny } 33515453e85SIra Weiny 336e7610581SKamal Heib static const struct ib_device_ops usnic_dev_ops = { 3377a154142SJason Gunthorpe .owner = THIS_MODULE, 338b9560a41SJason Gunthorpe .driver_id = RDMA_DRIVER_USNIC, 33972c6ec18SJason Gunthorpe .uverbs_abi_ver = USNIC_UVERBS_ABI_VERSION, 340b9560a41SJason Gunthorpe 341e7610581SKamal Heib .alloc_pd = usnic_ib_alloc_pd, 342e7610581SKamal Heib .alloc_ucontext = usnic_ib_alloc_ucontext, 343e7610581SKamal Heib .create_cq = usnic_ib_create_cq, 344e7610581SKamal Heib .create_qp = usnic_ib_create_qp, 345e7610581SKamal Heib .dealloc_pd = usnic_ib_dealloc_pd, 346e7610581SKamal Heib .dealloc_ucontext = usnic_ib_dealloc_ucontext, 347e7610581SKamal Heib .dereg_mr = usnic_ib_dereg_mr, 348e7610581SKamal Heib .destroy_cq = usnic_ib_destroy_cq, 349e7610581SKamal Heib .destroy_qp = usnic_ib_destroy_qp, 350e7610581SKamal Heib .get_dev_fw_str = usnic_get_dev_fw_str, 351e7610581SKamal Heib .get_link_layer = usnic_ib_port_link_layer, 352e7610581SKamal Heib .get_port_immutable = usnic_port_immutable, 353e7610581SKamal Heib .mmap = usnic_ib_mmap, 354e7610581SKamal Heib .modify_qp = usnic_ib_modify_qp, 355e7610581SKamal Heib .query_device = usnic_ib_query_device, 356e7610581SKamal Heib .query_gid = usnic_ib_query_gid, 357e7610581SKamal Heib .query_port = usnic_ib_query_port, 358e7610581SKamal Heib .query_qp = usnic_ib_query_qp, 359e7610581SKamal Heib .reg_user_mr = usnic_ib_reg_mr, 36021a428a0SLeon Romanovsky INIT_RDMA_OBJ_SIZE(ib_pd, usnic_ib_pd, ibpd), 361e39afe3dSLeon Romanovsky INIT_RDMA_OBJ_SIZE(ib_cq, usnic_ib_cq, ibcq), 362a2a074efSLeon Romanovsky INIT_RDMA_OBJ_SIZE(ib_ucontext, usnic_ib_ucontext, ibucontext), 363e7610581SKamal Heib }; 364e7610581SKamal Heib 365e3cf00d0SUpinder Malhi /* Start of PF discovery section */ 366e3cf00d0SUpinder Malhi static void *usnic_ib_device_add(struct pci_dev *dev) 367e3cf00d0SUpinder Malhi { 368e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev; 369e3cf00d0SUpinder Malhi union ib_gid gid; 3705d50f400SLeon Romanovsky struct in_device *ind; 371c7845bcaSUpinder Malhi struct net_device *netdev; 3725bb3c1e9SParvi Kaustubhi int ret; 373e3cf00d0SUpinder Malhi 374e3cf00d0SUpinder Malhi usnic_dbg("\n"); 375c7845bcaSUpinder Malhi netdev = pci_get_drvdata(dev); 376e3cf00d0SUpinder Malhi 377459cc69fSLeon Romanovsky us_ibdev = ib_alloc_device(usnic_ib_dev, ib_dev); 3782c79dad8SInsu Yun if (!us_ibdev) { 379e3cf00d0SUpinder Malhi usnic_err("Device %s context alloc failed\n", 380e3cf00d0SUpinder Malhi netdev_name(pci_get_drvdata(dev))); 3812c79dad8SInsu Yun return ERR_PTR(-EFAULT); 382e3cf00d0SUpinder Malhi } 383e3cf00d0SUpinder Malhi 384e3cf00d0SUpinder Malhi us_ibdev->ufdev = usnic_fwd_dev_alloc(dev); 3852c79dad8SInsu Yun if (!us_ibdev->ufdev) { 3862c79dad8SInsu Yun usnic_err("Failed to alloc ufdev for %s\n", pci_name(dev)); 387e3cf00d0SUpinder Malhi goto err_dealloc; 388e3cf00d0SUpinder Malhi } 389e3cf00d0SUpinder Malhi 390e3cf00d0SUpinder Malhi mutex_init(&us_ibdev->usdev_lock); 391e3cf00d0SUpinder Malhi INIT_LIST_HEAD(&us_ibdev->vf_dev_list); 392e3cf00d0SUpinder Malhi INIT_LIST_HEAD(&us_ibdev->ctx_list); 393e3cf00d0SUpinder Malhi 394e3cf00d0SUpinder Malhi us_ibdev->pdev = dev; 395e3cf00d0SUpinder Malhi us_ibdev->netdev = pci_get_drvdata(dev); 39661f78268SUpinder Malhi us_ibdev->ib_dev.node_type = RDMA_NODE_USNIC_UDP; 397e3cf00d0SUpinder Malhi us_ibdev->ib_dev.phys_port_cnt = USNIC_IB_PORT_CNT; 398e3cf00d0SUpinder Malhi us_ibdev->ib_dev.num_comp_vectors = USNIC_IB_NUM_COMP_VECTORS; 3996b06d52dSBart Van Assche us_ibdev->ib_dev.dev.parent = &dev->dev; 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 422508a523fSParav Pandit rdma_set_device_sysfs_group(&us_ibdev->ib_dev, &usnic_attr_group); 423508a523fSParav Pandit 4245bb3c1e9SParvi Kaustubhi ret = ib_device_set_netdev(&us_ibdev->ib_dev, us_ibdev->netdev, 1); 4255bb3c1e9SParvi Kaustubhi if (ret) 4265bb3c1e9SParvi Kaustubhi goto err_fwd_dealloc; 4275bb3c1e9SParvi Kaustubhi 428*e0477b34SJason Gunthorpe dma_set_max_seg_size(&dev->dev, SZ_2G); 429*e0477b34SJason Gunthorpe if (ib_register_device(&us_ibdev->ib_dev, "usnic_%d", &dev->dev)) 430e3cf00d0SUpinder Malhi goto err_fwd_dealloc; 431e3cf00d0SUpinder Malhi 4328af94ac6SUpinder Malhi usnic_fwd_set_mtu(us_ibdev->ufdev, us_ibdev->netdev->mtu); 4338af94ac6SUpinder Malhi usnic_fwd_set_mac(us_ibdev->ufdev, us_ibdev->netdev->dev_addr); 4348af94ac6SUpinder Malhi if (netif_carrier_ok(us_ibdev->netdev)) 4358af94ac6SUpinder Malhi usnic_fwd_carrier_up(us_ibdev->ufdev); 4368af94ac6SUpinder Malhi 4372638eb8bSFlorian Westphal rcu_read_lock(); 4382638eb8bSFlorian Westphal ind = __in_dev_get_rcu(netdev); 4392638eb8bSFlorian Westphal if (ind) { 4402638eb8bSFlorian Westphal const struct in_ifaddr *ifa; 4412638eb8bSFlorian Westphal 4422638eb8bSFlorian Westphal ifa = rcu_dereference(ind->ifa_list); 4432638eb8bSFlorian Westphal if (ifa) 4442638eb8bSFlorian Westphal usnic_fwd_add_ipaddr(us_ibdev->ufdev, ifa->ifa_address); 4452638eb8bSFlorian Westphal } 4462638eb8bSFlorian Westphal rcu_read_unlock(); 447c7845bcaSUpinder Malhi 448c7845bcaSUpinder Malhi usnic_mac_ip_to_gid(us_ibdev->netdev->perm_addr, 449c7845bcaSUpinder Malhi us_ibdev->ufdev->inaddr, &gid.raw[0]); 450e3cf00d0SUpinder Malhi memcpy(&us_ibdev->ib_dev.node_guid, &gid.global.interface_id, 451e3cf00d0SUpinder Malhi sizeof(gid.global.interface_id)); 452e3cf00d0SUpinder Malhi kref_init(&us_ibdev->vf_cnt); 453e3cf00d0SUpinder Malhi 454e3cf00d0SUpinder Malhi usnic_info("Added ibdev: %s netdev: %s with mac %pM Link: %u MTU: %u\n", 4559de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev), 4569de69861SJason Gunthorpe netdev_name(us_ibdev->netdev), us_ibdev->ufdev->mac, 4579de69861SJason Gunthorpe us_ibdev->ufdev->link_up, us_ibdev->ufdev->mtu); 458e3cf00d0SUpinder Malhi return us_ibdev; 459e3cf00d0SUpinder Malhi 460e3cf00d0SUpinder Malhi err_fwd_dealloc: 461e3cf00d0SUpinder Malhi usnic_fwd_dev_free(us_ibdev->ufdev); 462e3cf00d0SUpinder Malhi err_dealloc: 463e3cf00d0SUpinder Malhi usnic_err("failed -- deallocing device\n"); 464e3cf00d0SUpinder Malhi ib_dealloc_device(&us_ibdev->ib_dev); 465e3cf00d0SUpinder Malhi return NULL; 466e3cf00d0SUpinder Malhi } 467e3cf00d0SUpinder Malhi 468e3cf00d0SUpinder Malhi static void usnic_ib_device_remove(struct usnic_ib_dev *us_ibdev) 469e3cf00d0SUpinder Malhi { 4709de69861SJason Gunthorpe usnic_info("Unregistering %s\n", dev_name(&us_ibdev->ib_dev.dev)); 471e3cf00d0SUpinder Malhi usnic_ib_sysfs_unregister_usdev(us_ibdev); 472e3cf00d0SUpinder Malhi usnic_fwd_dev_free(us_ibdev->ufdev); 473e3cf00d0SUpinder Malhi ib_unregister_device(&us_ibdev->ib_dev); 474e3cf00d0SUpinder Malhi ib_dealloc_device(&us_ibdev->ib_dev); 475e3cf00d0SUpinder Malhi } 476e3cf00d0SUpinder Malhi 477e3cf00d0SUpinder Malhi static void usnic_ib_undiscover_pf(struct kref *kref) 478e3cf00d0SUpinder Malhi { 479e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev, *tmp; 480e3cf00d0SUpinder Malhi struct pci_dev *dev; 481e3cf00d0SUpinder Malhi bool found = false; 482e3cf00d0SUpinder Malhi 483e3cf00d0SUpinder Malhi dev = container_of(kref, struct usnic_ib_dev, vf_cnt)->pdev; 484e3cf00d0SUpinder Malhi mutex_lock(&usnic_ib_ibdev_list_lock); 485e3cf00d0SUpinder Malhi list_for_each_entry_safe(us_ibdev, tmp, 486e3cf00d0SUpinder Malhi &usnic_ib_ibdev_list, ib_dev_link) { 487e3cf00d0SUpinder Malhi if (us_ibdev->pdev == dev) { 488e3cf00d0SUpinder Malhi list_del(&us_ibdev->ib_dev_link); 489e3cf00d0SUpinder Malhi found = true; 490e3cf00d0SUpinder Malhi break; 491e3cf00d0SUpinder Malhi } 492e3cf00d0SUpinder Malhi } 493e3cf00d0SUpinder Malhi 494e3cf00d0SUpinder Malhi 495e3cf00d0SUpinder Malhi mutex_unlock(&usnic_ib_ibdev_list_lock); 4960c236606SParvi Kaustubhi if (found) 4970c236606SParvi Kaustubhi usnic_ib_device_remove(us_ibdev); 4980c236606SParvi Kaustubhi else 4990c236606SParvi Kaustubhi WARN(1, "Failed to remove PF %s\n", pci_name(dev)); 500e3cf00d0SUpinder Malhi } 501e3cf00d0SUpinder Malhi 502e3cf00d0SUpinder Malhi static struct usnic_ib_dev *usnic_ib_discover_pf(struct usnic_vnic *vnic) 503e3cf00d0SUpinder Malhi { 504e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev; 505e3cf00d0SUpinder Malhi struct pci_dev *parent_pci, *vf_pci; 506e3cf00d0SUpinder Malhi int err; 507e3cf00d0SUpinder Malhi 508e3cf00d0SUpinder Malhi vf_pci = usnic_vnic_get_pdev(vnic); 509e3cf00d0SUpinder Malhi parent_pci = pci_physfn(vf_pci); 510e3cf00d0SUpinder Malhi 511e3cf00d0SUpinder Malhi BUG_ON(!parent_pci); 512e3cf00d0SUpinder Malhi 513e3cf00d0SUpinder Malhi mutex_lock(&usnic_ib_ibdev_list_lock); 514e3cf00d0SUpinder Malhi list_for_each_entry(us_ibdev, &usnic_ib_ibdev_list, ib_dev_link) { 515e3cf00d0SUpinder Malhi if (us_ibdev->pdev == parent_pci) { 516e3cf00d0SUpinder Malhi kref_get(&us_ibdev->vf_cnt); 517e3cf00d0SUpinder Malhi goto out; 518e3cf00d0SUpinder Malhi } 519e3cf00d0SUpinder Malhi } 520e3cf00d0SUpinder Malhi 521e3cf00d0SUpinder Malhi us_ibdev = usnic_ib_device_add(parent_pci); 522e3cf00d0SUpinder Malhi if (IS_ERR_OR_NULL(us_ibdev)) { 5236a54d9f9SUpinder Malhi us_ibdev = us_ibdev ? us_ibdev : ERR_PTR(-EFAULT); 524e3cf00d0SUpinder Malhi goto out; 525e3cf00d0SUpinder Malhi } 526e3cf00d0SUpinder Malhi 527e3cf00d0SUpinder Malhi err = usnic_ib_sysfs_register_usdev(us_ibdev); 528e3cf00d0SUpinder Malhi if (err) { 529e3cf00d0SUpinder Malhi usnic_ib_device_remove(us_ibdev); 530e3cf00d0SUpinder Malhi us_ibdev = ERR_PTR(err); 531e3cf00d0SUpinder Malhi goto out; 532e3cf00d0SUpinder Malhi } 533e3cf00d0SUpinder Malhi 534e3cf00d0SUpinder Malhi list_add(&us_ibdev->ib_dev_link, &usnic_ib_ibdev_list); 535e3cf00d0SUpinder Malhi out: 536e3cf00d0SUpinder Malhi mutex_unlock(&usnic_ib_ibdev_list_lock); 537e3cf00d0SUpinder Malhi return us_ibdev; 538e3cf00d0SUpinder Malhi } 539e3cf00d0SUpinder Malhi /* End of PF discovery section */ 540e3cf00d0SUpinder Malhi 541e3cf00d0SUpinder Malhi /* Start of PCI section */ 542e3cf00d0SUpinder Malhi 5439baa3c34SBenoit Taine static const struct pci_device_id usnic_ib_pci_ids[] = { 544e3cf00d0SUpinder Malhi {PCI_DEVICE(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_USPACE_NIC)}, 545e3cf00d0SUpinder Malhi {0,} 546e3cf00d0SUpinder Malhi }; 547e3cf00d0SUpinder Malhi 548e3cf00d0SUpinder Malhi static int usnic_ib_pci_probe(struct pci_dev *pdev, 549e3cf00d0SUpinder Malhi const struct pci_device_id *id) 550e3cf00d0SUpinder Malhi { 551e3cf00d0SUpinder Malhi int err; 552e3cf00d0SUpinder Malhi struct usnic_ib_dev *pf; 553e3cf00d0SUpinder Malhi struct usnic_ib_vf *vf; 554e3cf00d0SUpinder Malhi enum usnic_vnic_res_type res_type; 555e3cf00d0SUpinder Malhi 556e3cf00d0SUpinder Malhi vf = kzalloc(sizeof(*vf), GFP_KERNEL); 557e3cf00d0SUpinder Malhi if (!vf) 558e3cf00d0SUpinder Malhi return -ENOMEM; 559e3cf00d0SUpinder Malhi 560e3cf00d0SUpinder Malhi err = pci_enable_device(pdev); 561e3cf00d0SUpinder Malhi if (err) { 562e3cf00d0SUpinder Malhi usnic_err("Failed to enable %s with err %d\n", 563e3cf00d0SUpinder Malhi pci_name(pdev), err); 564e3cf00d0SUpinder Malhi goto out_clean_vf; 565e3cf00d0SUpinder Malhi } 566e3cf00d0SUpinder Malhi 567e3cf00d0SUpinder Malhi err = pci_request_regions(pdev, DRV_NAME); 568e3cf00d0SUpinder Malhi if (err) { 569e3cf00d0SUpinder Malhi usnic_err("Failed to request region for %s with err %d\n", 570e3cf00d0SUpinder Malhi pci_name(pdev), err); 571e3cf00d0SUpinder Malhi goto out_disable_device; 572e3cf00d0SUpinder Malhi } 573e3cf00d0SUpinder Malhi 574e3cf00d0SUpinder Malhi pci_set_master(pdev); 575e3cf00d0SUpinder Malhi pci_set_drvdata(pdev, vf); 576e3cf00d0SUpinder Malhi 577e3cf00d0SUpinder Malhi vf->vnic = usnic_vnic_alloc(pdev); 578e3cf00d0SUpinder Malhi if (IS_ERR_OR_NULL(vf->vnic)) { 5796a54d9f9SUpinder Malhi err = vf->vnic ? PTR_ERR(vf->vnic) : -ENOMEM; 580e3cf00d0SUpinder Malhi usnic_err("Failed to alloc vnic for %s with err %d\n", 581e3cf00d0SUpinder Malhi pci_name(pdev), err); 582e3cf00d0SUpinder Malhi goto out_release_regions; 583e3cf00d0SUpinder Malhi } 584e3cf00d0SUpinder Malhi 585e3cf00d0SUpinder Malhi pf = usnic_ib_discover_pf(vf->vnic); 586e3cf00d0SUpinder Malhi if (IS_ERR_OR_NULL(pf)) { 587e3cf00d0SUpinder Malhi usnic_err("Failed to discover pf of vnic %s with err%ld\n", 588e3cf00d0SUpinder Malhi pci_name(pdev), PTR_ERR(pf)); 5896a54d9f9SUpinder Malhi err = pf ? PTR_ERR(pf) : -EFAULT; 590e3cf00d0SUpinder Malhi goto out_clean_vnic; 591e3cf00d0SUpinder Malhi } 592e3cf00d0SUpinder Malhi 593e3cf00d0SUpinder Malhi vf->pf = pf; 594e3cf00d0SUpinder Malhi spin_lock_init(&vf->lock); 595e3cf00d0SUpinder Malhi mutex_lock(&pf->usdev_lock); 596e3cf00d0SUpinder Malhi list_add_tail(&vf->link, &pf->vf_dev_list); 597e3cf00d0SUpinder Malhi /* 598e3cf00d0SUpinder Malhi * Save max settings (will be same for each VF, easier to re-write than 599e3cf00d0SUpinder Malhi * to say "if (!set) { set_values(); set=1; } 600e3cf00d0SUpinder Malhi */ 601e3cf00d0SUpinder Malhi for (res_type = USNIC_VNIC_RES_TYPE_EOL+1; 602e3cf00d0SUpinder Malhi res_type < USNIC_VNIC_RES_TYPE_MAX; 603e3cf00d0SUpinder Malhi res_type++) { 604e3cf00d0SUpinder Malhi pf->vf_res_cnt[res_type] = usnic_vnic_res_cnt(vf->vnic, 605e3cf00d0SUpinder Malhi res_type); 606e3cf00d0SUpinder Malhi } 607e3cf00d0SUpinder Malhi 608e3cf00d0SUpinder Malhi mutex_unlock(&pf->usdev_lock); 609e3cf00d0SUpinder Malhi 610e3cf00d0SUpinder Malhi usnic_info("Registering usnic VF %s into PF %s\n", pci_name(pdev), 6119de69861SJason Gunthorpe dev_name(&pf->ib_dev.dev)); 612e3cf00d0SUpinder Malhi usnic_ib_log_vf(vf); 613e3cf00d0SUpinder Malhi return 0; 614e3cf00d0SUpinder Malhi 615e3cf00d0SUpinder Malhi out_clean_vnic: 616e3cf00d0SUpinder Malhi usnic_vnic_free(vf->vnic); 617e3cf00d0SUpinder Malhi out_release_regions: 618e3cf00d0SUpinder Malhi pci_set_drvdata(pdev, NULL); 619e3cf00d0SUpinder Malhi pci_clear_master(pdev); 620e3cf00d0SUpinder Malhi pci_release_regions(pdev); 621e3cf00d0SUpinder Malhi out_disable_device: 622e3cf00d0SUpinder Malhi pci_disable_device(pdev); 623e3cf00d0SUpinder Malhi out_clean_vf: 624e3cf00d0SUpinder Malhi kfree(vf); 625e3cf00d0SUpinder Malhi return err; 626e3cf00d0SUpinder Malhi } 627e3cf00d0SUpinder Malhi 628e3cf00d0SUpinder Malhi static void usnic_ib_pci_remove(struct pci_dev *pdev) 629e3cf00d0SUpinder Malhi { 630e3cf00d0SUpinder Malhi struct usnic_ib_vf *vf = pci_get_drvdata(pdev); 631e3cf00d0SUpinder Malhi struct usnic_ib_dev *pf = vf->pf; 632e3cf00d0SUpinder Malhi 633e3cf00d0SUpinder Malhi mutex_lock(&pf->usdev_lock); 634e3cf00d0SUpinder Malhi list_del(&vf->link); 635e3cf00d0SUpinder Malhi mutex_unlock(&pf->usdev_lock); 636e3cf00d0SUpinder Malhi 637e3cf00d0SUpinder Malhi kref_put(&pf->vf_cnt, usnic_ib_undiscover_pf); 638e3cf00d0SUpinder Malhi usnic_vnic_free(vf->vnic); 639e3cf00d0SUpinder Malhi pci_set_drvdata(pdev, NULL); 640e3cf00d0SUpinder Malhi pci_clear_master(pdev); 641e3cf00d0SUpinder Malhi pci_release_regions(pdev); 642e3cf00d0SUpinder Malhi pci_disable_device(pdev); 643e3cf00d0SUpinder Malhi kfree(vf); 644e3cf00d0SUpinder Malhi 645e3cf00d0SUpinder Malhi usnic_info("Removed VF %s\n", pci_name(pdev)); 646e3cf00d0SUpinder Malhi } 647e3cf00d0SUpinder Malhi 648e3cf00d0SUpinder Malhi /* PCI driver entry points */ 649e3cf00d0SUpinder Malhi static struct pci_driver usnic_ib_pci_driver = { 650e3cf00d0SUpinder Malhi .name = DRV_NAME, 651e3cf00d0SUpinder Malhi .id_table = usnic_ib_pci_ids, 652e3cf00d0SUpinder Malhi .probe = usnic_ib_pci_probe, 653e3cf00d0SUpinder Malhi .remove = usnic_ib_pci_remove, 654e3cf00d0SUpinder Malhi }; 655e3cf00d0SUpinder Malhi /* End of PCI section */ 656e3cf00d0SUpinder Malhi 657e3cf00d0SUpinder Malhi /* Start of module section */ 658e3cf00d0SUpinder Malhi static int __init usnic_ib_init(void) 659e3cf00d0SUpinder Malhi { 660e3cf00d0SUpinder Malhi int err; 661e3cf00d0SUpinder Malhi 662e3cf00d0SUpinder Malhi printk_once(KERN_INFO "%s", usnic_version); 663e3cf00d0SUpinder Malhi 664e3cf00d0SUpinder Malhi err = usnic_uiom_init(DRV_NAME); 665e3cf00d0SUpinder Malhi if (err) { 666901018f2SColin Ian King usnic_err("Unable to initialize umem with err %d\n", err); 667e3cf00d0SUpinder Malhi return err; 668e3cf00d0SUpinder Malhi } 669e3cf00d0SUpinder Malhi 67086cd747cSChristophe Jaillet err = pci_register_driver(&usnic_ib_pci_driver); 67186cd747cSChristophe Jaillet if (err) { 672e3cf00d0SUpinder Malhi usnic_err("Unable to register with PCI\n"); 673e3cf00d0SUpinder Malhi goto out_umem_fini; 674e3cf00d0SUpinder Malhi } 675e3cf00d0SUpinder Malhi 676e3cf00d0SUpinder Malhi err = register_netdevice_notifier(&usnic_ib_netdevice_notifier); 677e3cf00d0SUpinder Malhi if (err) { 678e3cf00d0SUpinder Malhi usnic_err("Failed to register netdev notifier\n"); 679e3cf00d0SUpinder Malhi goto out_pci_unreg; 680e3cf00d0SUpinder Malhi } 681e3cf00d0SUpinder Malhi 682c7845bcaSUpinder Malhi err = register_inetaddr_notifier(&usnic_ib_inetaddr_notifier); 683c7845bcaSUpinder Malhi if (err) { 684c7845bcaSUpinder Malhi usnic_err("Failed to register inet addr notifier\n"); 685c7845bcaSUpinder Malhi goto out_unreg_netdev_notifier; 686c7845bcaSUpinder Malhi } 687c7845bcaSUpinder Malhi 688e3cf00d0SUpinder Malhi err = usnic_transport_init(); 689e3cf00d0SUpinder Malhi if (err) { 690e3cf00d0SUpinder Malhi usnic_err("Failed to initialize transport\n"); 691c7845bcaSUpinder Malhi goto out_unreg_inetaddr_notifier; 692e3cf00d0SUpinder Malhi } 693e3cf00d0SUpinder Malhi 694e3cf00d0SUpinder Malhi usnic_debugfs_init(); 695e3cf00d0SUpinder Malhi 696e3cf00d0SUpinder Malhi return 0; 697e3cf00d0SUpinder Malhi 698c7845bcaSUpinder Malhi out_unreg_inetaddr_notifier: 699c7845bcaSUpinder Malhi unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier); 700e3cf00d0SUpinder Malhi out_unreg_netdev_notifier: 701e3cf00d0SUpinder Malhi unregister_netdevice_notifier(&usnic_ib_netdevice_notifier); 702e3cf00d0SUpinder Malhi out_pci_unreg: 703e3cf00d0SUpinder Malhi pci_unregister_driver(&usnic_ib_pci_driver); 704e3cf00d0SUpinder Malhi out_umem_fini: 705e3cf00d0SUpinder Malhi 706e3cf00d0SUpinder Malhi return err; 707e3cf00d0SUpinder Malhi } 708e3cf00d0SUpinder Malhi 709e3cf00d0SUpinder Malhi static void __exit usnic_ib_destroy(void) 710e3cf00d0SUpinder Malhi { 711e3cf00d0SUpinder Malhi usnic_dbg("\n"); 712e3cf00d0SUpinder Malhi usnic_debugfs_exit(); 713e3cf00d0SUpinder Malhi usnic_transport_fini(); 714c7845bcaSUpinder Malhi unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier); 715e3cf00d0SUpinder Malhi unregister_netdevice_notifier(&usnic_ib_netdevice_notifier); 716e3cf00d0SUpinder Malhi pci_unregister_driver(&usnic_ib_pci_driver); 717e3cf00d0SUpinder Malhi } 718e3cf00d0SUpinder Malhi 719e3cf00d0SUpinder Malhi MODULE_DESCRIPTION("Cisco VIC (usNIC) Verbs Driver"); 720e3cf00d0SUpinder Malhi MODULE_AUTHOR("Upinder Malhi <umalhi@cisco.com>"); 721e3cf00d0SUpinder Malhi MODULE_LICENSE("Dual BSD/GPL"); 722e3cf00d0SUpinder Malhi module_param(usnic_log_lvl, uint, S_IRUGO | S_IWUSR); 723e3cf00d0SUpinder Malhi module_param(usnic_ib_share_vf, uint, S_IRUGO | S_IWUSR); 724e3cf00d0SUpinder Malhi MODULE_PARM_DESC(usnic_log_lvl, " Off=0, Err=1, Info=2, Debug=3"); 725e3cf00d0SUpinder Malhi MODULE_PARM_DESC(usnic_ib_share_vf, "Off=0, On=1 VF sharing amongst QPs"); 726e3cf00d0SUpinder Malhi MODULE_DEVICE_TABLE(pci, usnic_ib_pci_ids); 727e3cf00d0SUpinder Malhi 728e3cf00d0SUpinder Malhi module_init(usnic_ib_init); 729e3cf00d0SUpinder Malhi module_exit(usnic_ib_destroy); 730e3cf00d0SUpinder Malhi /* End of module section */ 731