709 lines · c
1/*2 * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.3 *4 * This software is available to you under a choice of one of two5 * licenses. You may choose to be licensed under the terms of the GNU6 * General Public License (GPL) Version 2, available from the file7 * COPYING in the main directory of this source tree, or the8 * BSD license below:9 *10 * Redistribution and use in source and binary forms, with or11 * without modification, are permitted provided that the following12 * conditions are met:13 *14 * - Redistributions of source code must retain the above15 * copyright notice, this list of conditions and the following16 * disclaimer.17 *18 * - Redistributions in binary form must reproduce the above19 * copyright notice, this list of conditions and the following20 * disclaimer in the documentation and/or other materials21 * provided with the distribution.22 *23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE30 * SOFTWARE.31 *32 * Author: Upinder Malhi <umalhi@cisco.com>33 * Author: Anant Deepak <anadeepa@cisco.com>34 * Author: Cesare Cantu' <cantuc@cisco.com>35 * Author: Jeff Squyres <jsquyres@cisco.com>36 * Author: Kiran Thirumalai <kithirum@cisco.com>37 * Author: Xuyang Wang <xuywang@cisco.com>38 * Author: Reese Faucette <rfaucett@cisco.com>39 *40 */41 42#include <linux/module.h>43#include <linux/inetdevice.h>44#include <linux/init.h>45#include <linux/slab.h>46#include <linux/errno.h>47#include <linux/pci.h>48#include <linux/netdevice.h>49 50#include <rdma/ib_user_verbs.h>51#include <rdma/ib_addr.h>52 53#include "usnic_abi.h"54#include "usnic_common_util.h"55#include "usnic_ib.h"56#include "usnic_ib_qp_grp.h"57#include "usnic_log.h"58#include "usnic_fwd.h"59#include "usnic_debugfs.h"60#include "usnic_ib_verbs.h"61#include "usnic_transport.h"62#include "usnic_uiom.h"63#include "usnic_ib_sysfs.h"64 65unsigned int usnic_log_lvl = USNIC_LOG_LVL_ERR;66unsigned int usnic_ib_share_vf = 1;67 68static const char usnic_version[] =69 DRV_NAME ": Cisco VIC (USNIC) Verbs Driver v"70 DRV_VERSION " (" DRV_RELDATE ")\n";71 72static DEFINE_MUTEX(usnic_ib_ibdev_list_lock);73static LIST_HEAD(usnic_ib_ibdev_list);74 75/* Callback dump funcs */76static int usnic_ib_dump_vf_hdr(void *obj, char *buf, int buf_sz)77{78 struct usnic_ib_vf *vf = obj;79 return scnprintf(buf, buf_sz, "PF: %s ", dev_name(&vf->pf->ib_dev.dev));80}81/* End callback dump funcs */82 83static void usnic_ib_dump_vf(struct usnic_ib_vf *vf, char *buf, int buf_sz)84{85 usnic_vnic_dump(vf->vnic, buf, buf_sz, vf,86 usnic_ib_dump_vf_hdr,87 usnic_ib_qp_grp_dump_hdr, usnic_ib_qp_grp_dump_rows);88}89 90void usnic_ib_log_vf(struct usnic_ib_vf *vf)91{92 char *buf = kzalloc(1000, GFP_KERNEL);93 94 if (!buf)95 return;96 97 usnic_ib_dump_vf(vf, buf, 1000);98 usnic_dbg("%s\n", buf);99 100 kfree(buf);101}102 103/* Start of netdev section */104static void usnic_ib_qp_grp_modify_active_to_err(struct usnic_ib_dev *us_ibdev)105{106 struct usnic_ib_ucontext *ctx;107 struct usnic_ib_qp_grp *qp_grp;108 enum ib_qp_state cur_state;109 int status;110 111 BUG_ON(!mutex_is_locked(&us_ibdev->usdev_lock));112 113 list_for_each_entry(ctx, &us_ibdev->ctx_list, link) {114 list_for_each_entry(qp_grp, &ctx->qp_grp_list, link) {115 cur_state = qp_grp->state;116 if (cur_state == IB_QPS_INIT ||117 cur_state == IB_QPS_RTR ||118 cur_state == IB_QPS_RTS) {119 status = usnic_ib_qp_grp_modify(qp_grp,120 IB_QPS_ERR,121 NULL);122 if (status) {123 usnic_err("Failed to transition qp grp %u from %s to %s\n",124 qp_grp->grp_id,125 usnic_ib_qp_grp_state_to_string126 (cur_state),127 usnic_ib_qp_grp_state_to_string128 (IB_QPS_ERR));129 }130 }131 }132 }133}134 135static void usnic_ib_handle_usdev_event(struct usnic_ib_dev *us_ibdev,136 unsigned long event)137{138 struct net_device *netdev;139 struct ib_event ib_event;140 141 memset(&ib_event, 0, sizeof(ib_event));142 143 mutex_lock(&us_ibdev->usdev_lock);144 netdev = us_ibdev->netdev;145 switch (event) {146 case NETDEV_REBOOT:147 usnic_info("PF Reset on %s\n", dev_name(&us_ibdev->ib_dev.dev));148 usnic_ib_qp_grp_modify_active_to_err(us_ibdev);149 ib_event.event = IB_EVENT_PORT_ERR;150 ib_event.device = &us_ibdev->ib_dev;151 ib_event.element.port_num = 1;152 ib_dispatch_event(&ib_event);153 break;154 case NETDEV_UP:155 case NETDEV_DOWN:156 case NETDEV_CHANGE:157 if (!us_ibdev->ufdev->link_up &&158 netif_carrier_ok(netdev)) {159 usnic_fwd_carrier_up(us_ibdev->ufdev);160 usnic_info("Link UP on %s\n",161 dev_name(&us_ibdev->ib_dev.dev));162 ib_event.event = IB_EVENT_PORT_ACTIVE;163 ib_event.device = &us_ibdev->ib_dev;164 ib_event.element.port_num = 1;165 ib_dispatch_event(&ib_event);166 } else if (us_ibdev->ufdev->link_up &&167 !netif_carrier_ok(netdev)) {168 usnic_fwd_carrier_down(us_ibdev->ufdev);169 usnic_info("Link DOWN on %s\n",170 dev_name(&us_ibdev->ib_dev.dev));171 usnic_ib_qp_grp_modify_active_to_err(us_ibdev);172 ib_event.event = IB_EVENT_PORT_ERR;173 ib_event.device = &us_ibdev->ib_dev;174 ib_event.element.port_num = 1;175 ib_dispatch_event(&ib_event);176 } else {177 usnic_dbg("Ignoring %s on %s\n",178 netdev_cmd_to_name(event),179 dev_name(&us_ibdev->ib_dev.dev));180 }181 break;182 case NETDEV_CHANGEADDR:183 if (!memcmp(us_ibdev->ufdev->mac, netdev->dev_addr,184 sizeof(us_ibdev->ufdev->mac))) {185 usnic_dbg("Ignoring addr change on %s\n",186 dev_name(&us_ibdev->ib_dev.dev));187 } else {188 usnic_info(" %s old mac: %pM new mac: %pM\n",189 dev_name(&us_ibdev->ib_dev.dev),190 us_ibdev->ufdev->mac,191 netdev->dev_addr);192 usnic_fwd_set_mac(us_ibdev->ufdev, netdev->dev_addr);193 usnic_ib_qp_grp_modify_active_to_err(us_ibdev);194 ib_event.event = IB_EVENT_GID_CHANGE;195 ib_event.device = &us_ibdev->ib_dev;196 ib_event.element.port_num = 1;197 ib_dispatch_event(&ib_event);198 }199 200 break;201 case NETDEV_CHANGEMTU:202 if (us_ibdev->ufdev->mtu != netdev->mtu) {203 usnic_info("MTU Change on %s old: %u new: %u\n",204 dev_name(&us_ibdev->ib_dev.dev),205 us_ibdev->ufdev->mtu, netdev->mtu);206 usnic_fwd_set_mtu(us_ibdev->ufdev, netdev->mtu);207 usnic_ib_qp_grp_modify_active_to_err(us_ibdev);208 } else {209 usnic_dbg("Ignoring MTU change on %s\n",210 dev_name(&us_ibdev->ib_dev.dev));211 }212 break;213 default:214 usnic_dbg("Ignoring event %s on %s",215 netdev_cmd_to_name(event),216 dev_name(&us_ibdev->ib_dev.dev));217 }218 mutex_unlock(&us_ibdev->usdev_lock);219}220 221static int usnic_ib_netdevice_event(struct notifier_block *notifier,222 unsigned long event, void *ptr)223{224 struct usnic_ib_dev *us_ibdev;225 struct ib_device *ibdev;226 227 struct net_device *netdev = netdev_notifier_info_to_dev(ptr);228 229 ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_USNIC);230 if (!ibdev)231 return NOTIFY_DONE;232 233 us_ibdev = container_of(ibdev, struct usnic_ib_dev, ib_dev);234 usnic_ib_handle_usdev_event(us_ibdev, event);235 ib_device_put(ibdev);236 return NOTIFY_DONE;237}238 239static struct notifier_block usnic_ib_netdevice_notifier = {240 .notifier_call = usnic_ib_netdevice_event241};242/* End of netdev section */243 244/* Start of inet section */245static int usnic_ib_handle_inet_event(struct usnic_ib_dev *us_ibdev,246 unsigned long event, void *ptr)247{248 struct in_ifaddr *ifa = ptr;249 struct ib_event ib_event;250 251 mutex_lock(&us_ibdev->usdev_lock);252 253 switch (event) {254 case NETDEV_DOWN:255 usnic_info("%s via ip notifiers",256 netdev_cmd_to_name(event));257 usnic_fwd_del_ipaddr(us_ibdev->ufdev);258 usnic_ib_qp_grp_modify_active_to_err(us_ibdev);259 ib_event.event = IB_EVENT_GID_CHANGE;260 ib_event.device = &us_ibdev->ib_dev;261 ib_event.element.port_num = 1;262 ib_dispatch_event(&ib_event);263 break;264 case NETDEV_UP:265 usnic_fwd_add_ipaddr(us_ibdev->ufdev, ifa->ifa_address);266 usnic_info("%s via ip notifiers: ip %pI4",267 netdev_cmd_to_name(event),268 &us_ibdev->ufdev->inaddr);269 ib_event.event = IB_EVENT_GID_CHANGE;270 ib_event.device = &us_ibdev->ib_dev;271 ib_event.element.port_num = 1;272 ib_dispatch_event(&ib_event);273 break;274 default:275 usnic_info("Ignoring event %s on %s",276 netdev_cmd_to_name(event),277 dev_name(&us_ibdev->ib_dev.dev));278 }279 mutex_unlock(&us_ibdev->usdev_lock);280 281 return NOTIFY_DONE;282}283 284static int usnic_ib_inetaddr_event(struct notifier_block *notifier,285 unsigned long event, void *ptr)286{287 struct usnic_ib_dev *us_ibdev;288 struct in_ifaddr *ifa = ptr;289 struct net_device *netdev = ifa->ifa_dev->dev;290 struct ib_device *ibdev;291 292 ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_USNIC);293 if (!ibdev)294 return NOTIFY_DONE;295 296 us_ibdev = container_of(ibdev, struct usnic_ib_dev, ib_dev);297 usnic_ib_handle_inet_event(us_ibdev, event, ptr);298 ib_device_put(ibdev);299 return NOTIFY_DONE;300}301static struct notifier_block usnic_ib_inetaddr_notifier = {302 .notifier_call = usnic_ib_inetaddr_event303};304/* End of inet section*/305 306static int usnic_port_immutable(struct ib_device *ibdev, u32 port_num,307 struct ib_port_immutable *immutable)308{309 struct ib_port_attr attr;310 int err;311 312 immutable->core_cap_flags = RDMA_CORE_PORT_USNIC;313 314 err = ib_query_port(ibdev, port_num, &attr);315 if (err)316 return err;317 318 immutable->gid_tbl_len = attr.gid_tbl_len;319 320 return 0;321}322 323static void usnic_get_dev_fw_str(struct ib_device *device, char *str)324{325 struct usnic_ib_dev *us_ibdev =326 container_of(device, struct usnic_ib_dev, ib_dev);327 struct ethtool_drvinfo info;328 329 mutex_lock(&us_ibdev->usdev_lock);330 us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info);331 mutex_unlock(&us_ibdev->usdev_lock);332 333 snprintf(str, IB_FW_VERSION_NAME_MAX, "%s", info.fw_version);334}335 336static const struct ib_device_ops usnic_dev_ops = {337 .owner = THIS_MODULE,338 .driver_id = RDMA_DRIVER_USNIC,339 .uverbs_abi_ver = USNIC_UVERBS_ABI_VERSION,340 341 .alloc_pd = usnic_ib_alloc_pd,342 .alloc_ucontext = usnic_ib_alloc_ucontext,343 .create_cq = usnic_ib_create_cq,344 .create_qp = usnic_ib_create_qp,345 .dealloc_pd = usnic_ib_dealloc_pd,346 .dealloc_ucontext = usnic_ib_dealloc_ucontext,347 .dereg_mr = usnic_ib_dereg_mr,348 .destroy_cq = usnic_ib_destroy_cq,349 .destroy_qp = usnic_ib_destroy_qp,350 .device_group = &usnic_attr_group,351 .get_dev_fw_str = usnic_get_dev_fw_str,352 .get_link_layer = usnic_ib_port_link_layer,353 .get_port_immutable = usnic_port_immutable,354 .mmap = usnic_ib_mmap,355 .modify_qp = usnic_ib_modify_qp,356 .query_device = usnic_ib_query_device,357 .query_gid = usnic_ib_query_gid,358 .query_port = usnic_ib_query_port,359 .query_qp = usnic_ib_query_qp,360 .reg_user_mr = usnic_ib_reg_mr,361 INIT_RDMA_OBJ_SIZE(ib_pd, usnic_ib_pd, ibpd),362 INIT_RDMA_OBJ_SIZE(ib_cq, usnic_ib_cq, ibcq),363 INIT_RDMA_OBJ_SIZE(ib_qp, usnic_ib_qp_grp, ibqp),364 INIT_RDMA_OBJ_SIZE(ib_ucontext, usnic_ib_ucontext, ibucontext),365};366 367/* Start of PF discovery section */368static void *usnic_ib_device_add(struct pci_dev *dev)369{370 struct usnic_ib_dev *us_ibdev;371 union ib_gid gid;372 struct in_device *ind;373 struct net_device *netdev;374 int ret;375 376 usnic_dbg("\n");377 netdev = pci_get_drvdata(dev);378 379 us_ibdev = ib_alloc_device(usnic_ib_dev, ib_dev);380 if (!us_ibdev) {381 usnic_err("Device %s context alloc failed\n",382 netdev_name(pci_get_drvdata(dev)));383 return ERR_PTR(-EFAULT);384 }385 386 us_ibdev->ufdev = usnic_fwd_dev_alloc(dev);387 if (!us_ibdev->ufdev) {388 usnic_err("Failed to alloc ufdev for %s\n", pci_name(dev));389 goto err_dealloc;390 }391 392 mutex_init(&us_ibdev->usdev_lock);393 INIT_LIST_HEAD(&us_ibdev->vf_dev_list);394 INIT_LIST_HEAD(&us_ibdev->ctx_list);395 396 us_ibdev->pdev = dev;397 us_ibdev->netdev = pci_get_drvdata(dev);398 us_ibdev->ib_dev.node_type = RDMA_NODE_USNIC_UDP;399 us_ibdev->ib_dev.phys_port_cnt = USNIC_IB_PORT_CNT;400 us_ibdev->ib_dev.num_comp_vectors = USNIC_IB_NUM_COMP_VECTORS;401 us_ibdev->ib_dev.dev.parent = &dev->dev;402 403 ib_set_device_ops(&us_ibdev->ib_dev, &usnic_dev_ops);404 405 ret = ib_device_set_netdev(&us_ibdev->ib_dev, us_ibdev->netdev, 1);406 if (ret)407 goto err_fwd_dealloc;408 409 dma_set_max_seg_size(&dev->dev, SZ_2G);410 if (ib_register_device(&us_ibdev->ib_dev, "usnic_%d", &dev->dev))411 goto err_fwd_dealloc;412 413 usnic_fwd_set_mtu(us_ibdev->ufdev, us_ibdev->netdev->mtu);414 usnic_fwd_set_mac(us_ibdev->ufdev, us_ibdev->netdev->dev_addr);415 if (netif_carrier_ok(us_ibdev->netdev))416 usnic_fwd_carrier_up(us_ibdev->ufdev);417 418 rcu_read_lock();419 ind = __in_dev_get_rcu(netdev);420 if (ind) {421 const struct in_ifaddr *ifa;422 423 ifa = rcu_dereference(ind->ifa_list);424 if (ifa)425 usnic_fwd_add_ipaddr(us_ibdev->ufdev, ifa->ifa_address);426 }427 rcu_read_unlock();428 429 usnic_mac_ip_to_gid(us_ibdev->netdev->perm_addr,430 us_ibdev->ufdev->inaddr, &gid.raw[0]);431 memcpy(&us_ibdev->ib_dev.node_guid, &gid.global.interface_id,432 sizeof(gid.global.interface_id));433 kref_init(&us_ibdev->vf_cnt);434 435 usnic_info("Added ibdev: %s netdev: %s with mac %pM Link: %u MTU: %u\n",436 dev_name(&us_ibdev->ib_dev.dev),437 netdev_name(us_ibdev->netdev), us_ibdev->ufdev->mac,438 us_ibdev->ufdev->link_up, us_ibdev->ufdev->mtu);439 return us_ibdev;440 441err_fwd_dealloc:442 usnic_fwd_dev_free(us_ibdev->ufdev);443err_dealloc:444 usnic_err("failed -- deallocing device\n");445 ib_dealloc_device(&us_ibdev->ib_dev);446 return NULL;447}448 449static void usnic_ib_device_remove(struct usnic_ib_dev *us_ibdev)450{451 usnic_info("Unregistering %s\n", dev_name(&us_ibdev->ib_dev.dev));452 usnic_ib_sysfs_unregister_usdev(us_ibdev);453 usnic_fwd_dev_free(us_ibdev->ufdev);454 ib_unregister_device(&us_ibdev->ib_dev);455 ib_dealloc_device(&us_ibdev->ib_dev);456}457 458static void usnic_ib_undiscover_pf(struct kref *kref)459{460 struct usnic_ib_dev *us_ibdev, *tmp;461 struct pci_dev *dev;462 bool found = false;463 464 dev = container_of(kref, struct usnic_ib_dev, vf_cnt)->pdev;465 mutex_lock(&usnic_ib_ibdev_list_lock);466 list_for_each_entry_safe(us_ibdev, tmp,467 &usnic_ib_ibdev_list, ib_dev_link) {468 if (us_ibdev->pdev == dev) {469 list_del(&us_ibdev->ib_dev_link);470 found = true;471 break;472 }473 }474 475 476 mutex_unlock(&usnic_ib_ibdev_list_lock);477 if (found)478 usnic_ib_device_remove(us_ibdev);479 else480 WARN(1, "Failed to remove PF %s\n", pci_name(dev));481}482 483static struct usnic_ib_dev *usnic_ib_discover_pf(struct usnic_vnic *vnic)484{485 struct usnic_ib_dev *us_ibdev;486 struct pci_dev *parent_pci, *vf_pci;487 int err;488 489 vf_pci = usnic_vnic_get_pdev(vnic);490 parent_pci = pci_physfn(vf_pci);491 492 BUG_ON(!parent_pci);493 494 mutex_lock(&usnic_ib_ibdev_list_lock);495 list_for_each_entry(us_ibdev, &usnic_ib_ibdev_list, ib_dev_link) {496 if (us_ibdev->pdev == parent_pci) {497 kref_get(&us_ibdev->vf_cnt);498 goto out;499 }500 }501 502 us_ibdev = usnic_ib_device_add(parent_pci);503 if (IS_ERR_OR_NULL(us_ibdev)) {504 us_ibdev = us_ibdev ? us_ibdev : ERR_PTR(-EFAULT);505 goto out;506 }507 508 err = usnic_ib_sysfs_register_usdev(us_ibdev);509 if (err) {510 usnic_ib_device_remove(us_ibdev);511 us_ibdev = ERR_PTR(err);512 goto out;513 }514 515 list_add(&us_ibdev->ib_dev_link, &usnic_ib_ibdev_list);516out:517 mutex_unlock(&usnic_ib_ibdev_list_lock);518 return us_ibdev;519}520/* End of PF discovery section */521 522/* Start of PCI section */523 524static const struct pci_device_id usnic_ib_pci_ids[] = {525 {PCI_DEVICE(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_USPACE_NIC)},526 {0,}527};528 529static int usnic_ib_pci_probe(struct pci_dev *pdev,530 const struct pci_device_id *id)531{532 int err;533 struct usnic_ib_dev *pf;534 struct usnic_ib_vf *vf;535 enum usnic_vnic_res_type res_type;536 537 if (!device_iommu_mapped(&pdev->dev)) {538 usnic_err("IOMMU required but not present or enabled. USNIC QPs will not function w/o enabling IOMMU\n");539 return -EPERM;540 }541 542 vf = kzalloc(sizeof(*vf), GFP_KERNEL);543 if (!vf)544 return -ENOMEM;545 546 err = pci_enable_device(pdev);547 if (err) {548 usnic_err("Failed to enable %s with err %d\n",549 pci_name(pdev), err);550 goto out_clean_vf;551 }552 553 err = pci_request_regions(pdev, DRV_NAME);554 if (err) {555 usnic_err("Failed to request region for %s with err %d\n",556 pci_name(pdev), err);557 goto out_disable_device;558 }559 560 pci_set_master(pdev);561 pci_set_drvdata(pdev, vf);562 563 vf->vnic = usnic_vnic_alloc(pdev);564 if (IS_ERR_OR_NULL(vf->vnic)) {565 err = vf->vnic ? PTR_ERR(vf->vnic) : -ENOMEM;566 usnic_err("Failed to alloc vnic for %s with err %d\n",567 pci_name(pdev), err);568 goto out_release_regions;569 }570 571 pf = usnic_ib_discover_pf(vf->vnic);572 if (IS_ERR_OR_NULL(pf)) {573 usnic_err("Failed to discover pf of vnic %s with err%ld\n",574 pci_name(pdev), PTR_ERR(pf));575 err = pf ? PTR_ERR(pf) : -EFAULT;576 goto out_clean_vnic;577 }578 579 vf->pf = pf;580 mutex_init(&vf->lock);581 mutex_lock(&pf->usdev_lock);582 list_add_tail(&vf->link, &pf->vf_dev_list);583 /*584 * Save max settings (will be same for each VF, easier to re-write than585 * to say "if (!set) { set_values(); set=1; }586 */587 for (res_type = USNIC_VNIC_RES_TYPE_EOL+1;588 res_type < USNIC_VNIC_RES_TYPE_MAX;589 res_type++) {590 pf->vf_res_cnt[res_type] = usnic_vnic_res_cnt(vf->vnic,591 res_type);592 }593 594 mutex_unlock(&pf->usdev_lock);595 596 usnic_info("Registering usnic VF %s into PF %s\n", pci_name(pdev),597 dev_name(&pf->ib_dev.dev));598 usnic_ib_log_vf(vf);599 return 0;600 601out_clean_vnic:602 usnic_vnic_free(vf->vnic);603out_release_regions:604 pci_set_drvdata(pdev, NULL);605 pci_release_regions(pdev);606out_disable_device:607 pci_disable_device(pdev);608out_clean_vf:609 kfree(vf);610 return err;611}612 613static void usnic_ib_pci_remove(struct pci_dev *pdev)614{615 struct usnic_ib_vf *vf = pci_get_drvdata(pdev);616 struct usnic_ib_dev *pf = vf->pf;617 618 mutex_lock(&pf->usdev_lock);619 list_del(&vf->link);620 mutex_unlock(&pf->usdev_lock);621 622 kref_put(&pf->vf_cnt, usnic_ib_undiscover_pf);623 usnic_vnic_free(vf->vnic);624 pci_set_drvdata(pdev, NULL);625 pci_release_regions(pdev);626 pci_disable_device(pdev);627 kfree(vf);628 629 usnic_info("Removed VF %s\n", pci_name(pdev));630}631 632/* PCI driver entry points */633static struct pci_driver usnic_ib_pci_driver = {634 .name = DRV_NAME,635 .id_table = usnic_ib_pci_ids,636 .probe = usnic_ib_pci_probe,637 .remove = usnic_ib_pci_remove,638};639/* End of PCI section */640 641/* Start of module section */642static int __init usnic_ib_init(void)643{644 int err;645 646 printk_once(KERN_INFO "%s", usnic_version);647 648 err = pci_register_driver(&usnic_ib_pci_driver);649 if (err) {650 usnic_err("Unable to register with PCI\n");651 goto out_umem_fini;652 }653 654 err = register_netdevice_notifier(&usnic_ib_netdevice_notifier);655 if (err) {656 usnic_err("Failed to register netdev notifier\n");657 goto out_pci_unreg;658 }659 660 err = register_inetaddr_notifier(&usnic_ib_inetaddr_notifier);661 if (err) {662 usnic_err("Failed to register inet addr notifier\n");663 goto out_unreg_netdev_notifier;664 }665 666 err = usnic_transport_init();667 if (err) {668 usnic_err("Failed to initialize transport\n");669 goto out_unreg_inetaddr_notifier;670 }671 672 usnic_debugfs_init();673 674 return 0;675 676out_unreg_inetaddr_notifier:677 unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier);678out_unreg_netdev_notifier:679 unregister_netdevice_notifier(&usnic_ib_netdevice_notifier);680out_pci_unreg:681 pci_unregister_driver(&usnic_ib_pci_driver);682out_umem_fini:683 684 return err;685}686 687static void __exit usnic_ib_destroy(void)688{689 usnic_dbg("\n");690 usnic_debugfs_exit();691 usnic_transport_fini();692 unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier);693 unregister_netdevice_notifier(&usnic_ib_netdevice_notifier);694 pci_unregister_driver(&usnic_ib_pci_driver);695}696 697MODULE_DESCRIPTION("Cisco VIC (usNIC) Verbs Driver");698MODULE_AUTHOR("Upinder Malhi <umalhi@cisco.com>");699MODULE_LICENSE("Dual BSD/GPL");700module_param(usnic_log_lvl, uint, S_IRUGO | S_IWUSR);701module_param(usnic_ib_share_vf, uint, S_IRUGO | S_IWUSR);702MODULE_PARM_DESC(usnic_log_lvl, " Off=0, Err=1, Info=2, Debug=3");703MODULE_PARM_DESC(usnic_ib_share_vf, "Off=0, On=1 VF sharing amongst QPs");704MODULE_DEVICE_TABLE(pci, usnic_ib_pci_ids);705 706module_init(usnic_ib_init);707module_exit(usnic_ib_destroy);708/* End of module section */709