1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * vDPA bus. 4 * 5 * Copyright (c) 2020, Red Hat. All rights reserved. 6 * Author: Jason Wang <jasowang@redhat.com> 7 * 8 */ 9 10 #include <linux/module.h> 11 #include <linux/idr.h> 12 #include <linux/slab.h> 13 #include <linux/vdpa.h> 14 #include <uapi/linux/vdpa.h> 15 #include <net/genetlink.h> 16 #include <linux/mod_devicetable.h> 17 18 static LIST_HEAD(mdev_head); 19 /* A global mutex that protects vdpa management device and device level operations. */ 20 static DEFINE_MUTEX(vdpa_dev_mutex); 21 static DEFINE_IDA(vdpa_index_ida); 22 23 static struct genl_family vdpa_nl_family; 24 25 static int vdpa_dev_probe(struct device *d) 26 { 27 struct vdpa_device *vdev = dev_to_vdpa(d); 28 struct vdpa_driver *drv = drv_to_vdpa(vdev->dev.driver); 29 int ret = 0; 30 31 if (drv && drv->probe) 32 ret = drv->probe(vdev); 33 34 return ret; 35 } 36 37 static int vdpa_dev_remove(struct device *d) 38 { 39 struct vdpa_device *vdev = dev_to_vdpa(d); 40 struct vdpa_driver *drv = drv_to_vdpa(vdev->dev.driver); 41 42 if (drv && drv->remove) 43 drv->remove(vdev); 44 45 return 0; 46 } 47 48 static struct bus_type vdpa_bus = { 49 .name = "vdpa", 50 .probe = vdpa_dev_probe, 51 .remove = vdpa_dev_remove, 52 }; 53 54 static void vdpa_release_dev(struct device *d) 55 { 56 struct vdpa_device *vdev = dev_to_vdpa(d); 57 const struct vdpa_config_ops *ops = vdev->config; 58 59 if (ops->free) 60 ops->free(vdev); 61 62 ida_simple_remove(&vdpa_index_ida, vdev->index); 63 kfree(vdev); 64 } 65 66 /** 67 * __vdpa_alloc_device - allocate and initilaize a vDPA device 68 * This allows driver to some prepartion after device is 69 * initialized but before registered. 70 * @parent: the parent device 71 * @config: the bus operations that is supported by this device 72 * @size: size of the parent structure that contains private data 73 * @name: name of the vdpa device; optional. 74 * 75 * Driver should use vdpa_alloc_device() wrapper macro instead of 76 * using this directly. 77 * 78 * Return: Returns an error when parent/config/dma_dev is not set or fail to get 79 * ida. 80 */ 81 struct vdpa_device *__vdpa_alloc_device(struct device *parent, 82 const struct vdpa_config_ops *config, 83 size_t size, const char *name) 84 { 85 struct vdpa_device *vdev; 86 int err = -EINVAL; 87 88 if (!config) 89 goto err; 90 91 if (!!config->dma_map != !!config->dma_unmap) 92 goto err; 93 94 err = -ENOMEM; 95 vdev = kzalloc(size, GFP_KERNEL); 96 if (!vdev) 97 goto err; 98 99 err = ida_alloc(&vdpa_index_ida, GFP_KERNEL); 100 if (err < 0) 101 goto err_ida; 102 103 vdev->dev.bus = &vdpa_bus; 104 vdev->dev.parent = parent; 105 vdev->dev.release = vdpa_release_dev; 106 vdev->index = err; 107 vdev->config = config; 108 vdev->features_valid = false; 109 110 if (name) 111 err = dev_set_name(&vdev->dev, "%s", name); 112 else 113 err = dev_set_name(&vdev->dev, "vdpa%u", vdev->index); 114 if (err) 115 goto err_name; 116 117 device_initialize(&vdev->dev); 118 119 return vdev; 120 121 err_name: 122 ida_simple_remove(&vdpa_index_ida, vdev->index); 123 err_ida: 124 kfree(vdev); 125 err: 126 return ERR_PTR(err); 127 } 128 EXPORT_SYMBOL_GPL(__vdpa_alloc_device); 129 130 static int vdpa_name_match(struct device *dev, const void *data) 131 { 132 struct vdpa_device *vdev = container_of(dev, struct vdpa_device, dev); 133 134 return (strcmp(dev_name(&vdev->dev), data) == 0); 135 } 136 137 static int __vdpa_register_device(struct vdpa_device *vdev, int nvqs) 138 { 139 struct device *dev; 140 141 vdev->nvqs = nvqs; 142 143 lockdep_assert_held(&vdpa_dev_mutex); 144 dev = bus_find_device(&vdpa_bus, NULL, dev_name(&vdev->dev), vdpa_name_match); 145 if (dev) { 146 put_device(dev); 147 return -EEXIST; 148 } 149 return device_add(&vdev->dev); 150 } 151 152 /** 153 * _vdpa_register_device - register a vDPA device with vdpa lock held 154 * Caller must have a succeed call of vdpa_alloc_device() before. 155 * Caller must invoke this routine in the management device dev_add() 156 * callback after setting up valid mgmtdev for this vdpa device. 157 * @vdev: the vdpa device to be registered to vDPA bus 158 * @nvqs: number of virtqueues supported by this device 159 * 160 * Return: Returns an error when fail to add device to vDPA bus 161 */ 162 int _vdpa_register_device(struct vdpa_device *vdev, int nvqs) 163 { 164 if (!vdev->mdev) 165 return -EINVAL; 166 167 return __vdpa_register_device(vdev, nvqs); 168 } 169 EXPORT_SYMBOL_GPL(_vdpa_register_device); 170 171 /** 172 * vdpa_register_device - register a vDPA device 173 * Callers must have a succeed call of vdpa_alloc_device() before. 174 * @vdev: the vdpa device to be registered to vDPA bus 175 * @nvqs: number of virtqueues supported by this device 176 * 177 * Return: Returns an error when fail to add to vDPA bus 178 */ 179 int vdpa_register_device(struct vdpa_device *vdev, int nvqs) 180 { 181 int err; 182 183 mutex_lock(&vdpa_dev_mutex); 184 err = __vdpa_register_device(vdev, nvqs); 185 mutex_unlock(&vdpa_dev_mutex); 186 return err; 187 } 188 EXPORT_SYMBOL_GPL(vdpa_register_device); 189 190 /** 191 * _vdpa_unregister_device - unregister a vDPA device 192 * Caller must invoke this routine as part of management device dev_del() 193 * callback. 194 * @vdev: the vdpa device to be unregisted from vDPA bus 195 */ 196 void _vdpa_unregister_device(struct vdpa_device *vdev) 197 { 198 lockdep_assert_held(&vdpa_dev_mutex); 199 WARN_ON(!vdev->mdev); 200 device_unregister(&vdev->dev); 201 } 202 EXPORT_SYMBOL_GPL(_vdpa_unregister_device); 203 204 /** 205 * vdpa_unregister_device - unregister a vDPA device 206 * @vdev: the vdpa device to be unregisted from vDPA bus 207 */ 208 void vdpa_unregister_device(struct vdpa_device *vdev) 209 { 210 mutex_lock(&vdpa_dev_mutex); 211 device_unregister(&vdev->dev); 212 mutex_unlock(&vdpa_dev_mutex); 213 } 214 EXPORT_SYMBOL_GPL(vdpa_unregister_device); 215 216 /** 217 * __vdpa_register_driver - register a vDPA device driver 218 * @drv: the vdpa device driver to be registered 219 * @owner: module owner of the driver 220 * 221 * Return: Returns an err when fail to do the registration 222 */ 223 int __vdpa_register_driver(struct vdpa_driver *drv, struct module *owner) 224 { 225 drv->driver.bus = &vdpa_bus; 226 drv->driver.owner = owner; 227 228 return driver_register(&drv->driver); 229 } 230 EXPORT_SYMBOL_GPL(__vdpa_register_driver); 231 232 /** 233 * vdpa_unregister_driver - unregister a vDPA device driver 234 * @drv: the vdpa device driver to be unregistered 235 */ 236 void vdpa_unregister_driver(struct vdpa_driver *drv) 237 { 238 driver_unregister(&drv->driver); 239 } 240 EXPORT_SYMBOL_GPL(vdpa_unregister_driver); 241 242 /** 243 * vdpa_mgmtdev_register - register a vdpa management device 244 * 245 * @mdev: Pointer to vdpa management device 246 * vdpa_mgmtdev_register() register a vdpa management device which supports 247 * vdpa device management. 248 * Return: Returns 0 on success or failure when required callback ops are not 249 * initialized. 250 */ 251 int vdpa_mgmtdev_register(struct vdpa_mgmt_dev *mdev) 252 { 253 if (!mdev->device || !mdev->ops || !mdev->ops->dev_add || !mdev->ops->dev_del) 254 return -EINVAL; 255 256 INIT_LIST_HEAD(&mdev->list); 257 mutex_lock(&vdpa_dev_mutex); 258 list_add_tail(&mdev->list, &mdev_head); 259 mutex_unlock(&vdpa_dev_mutex); 260 return 0; 261 } 262 EXPORT_SYMBOL_GPL(vdpa_mgmtdev_register); 263 264 static int vdpa_match_remove(struct device *dev, void *data) 265 { 266 struct vdpa_device *vdev = container_of(dev, struct vdpa_device, dev); 267 struct vdpa_mgmt_dev *mdev = vdev->mdev; 268 269 if (mdev == data) 270 mdev->ops->dev_del(mdev, vdev); 271 return 0; 272 } 273 274 void vdpa_mgmtdev_unregister(struct vdpa_mgmt_dev *mdev) 275 { 276 mutex_lock(&vdpa_dev_mutex); 277 278 list_del(&mdev->list); 279 280 /* Filter out all the entries belong to this management device and delete it. */ 281 bus_for_each_dev(&vdpa_bus, NULL, mdev, vdpa_match_remove); 282 283 mutex_unlock(&vdpa_dev_mutex); 284 } 285 EXPORT_SYMBOL_GPL(vdpa_mgmtdev_unregister); 286 287 static bool mgmtdev_handle_match(const struct vdpa_mgmt_dev *mdev, 288 const char *busname, const char *devname) 289 { 290 /* Bus name is optional for simulated management device, so ignore the 291 * device with bus if bus attribute is provided. 292 */ 293 if ((busname && !mdev->device->bus) || (!busname && mdev->device->bus)) 294 return false; 295 296 if (!busname && strcmp(dev_name(mdev->device), devname) == 0) 297 return true; 298 299 if (busname && (strcmp(mdev->device->bus->name, busname) == 0) && 300 (strcmp(dev_name(mdev->device), devname) == 0)) 301 return true; 302 303 return false; 304 } 305 306 static struct vdpa_mgmt_dev *vdpa_mgmtdev_get_from_attr(struct nlattr **attrs) 307 { 308 struct vdpa_mgmt_dev *mdev; 309 const char *busname = NULL; 310 const char *devname; 311 312 if (!attrs[VDPA_ATTR_MGMTDEV_DEV_NAME]) 313 return ERR_PTR(-EINVAL); 314 devname = nla_data(attrs[VDPA_ATTR_MGMTDEV_DEV_NAME]); 315 if (attrs[VDPA_ATTR_MGMTDEV_BUS_NAME]) 316 busname = nla_data(attrs[VDPA_ATTR_MGMTDEV_BUS_NAME]); 317 318 list_for_each_entry(mdev, &mdev_head, list) { 319 if (mgmtdev_handle_match(mdev, busname, devname)) 320 return mdev; 321 } 322 return ERR_PTR(-ENODEV); 323 } 324 325 static int vdpa_nl_mgmtdev_handle_fill(struct sk_buff *msg, const struct vdpa_mgmt_dev *mdev) 326 { 327 if (mdev->device->bus && 328 nla_put_string(msg, VDPA_ATTR_MGMTDEV_BUS_NAME, mdev->device->bus->name)) 329 return -EMSGSIZE; 330 if (nla_put_string(msg, VDPA_ATTR_MGMTDEV_DEV_NAME, dev_name(mdev->device))) 331 return -EMSGSIZE; 332 return 0; 333 } 334 335 static int vdpa_mgmtdev_fill(const struct vdpa_mgmt_dev *mdev, struct sk_buff *msg, 336 u32 portid, u32 seq, int flags) 337 { 338 u64 supported_classes = 0; 339 void *hdr; 340 int i = 0; 341 int err; 342 343 hdr = genlmsg_put(msg, portid, seq, &vdpa_nl_family, flags, VDPA_CMD_MGMTDEV_NEW); 344 if (!hdr) 345 return -EMSGSIZE; 346 err = vdpa_nl_mgmtdev_handle_fill(msg, mdev); 347 if (err) 348 goto msg_err; 349 350 while (mdev->id_table[i].device) { 351 supported_classes |= BIT(mdev->id_table[i].device); 352 i++; 353 } 354 355 if (nla_put_u64_64bit(msg, VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES, 356 supported_classes, VDPA_ATTR_UNSPEC)) { 357 err = -EMSGSIZE; 358 goto msg_err; 359 } 360 361 genlmsg_end(msg, hdr); 362 return 0; 363 364 msg_err: 365 genlmsg_cancel(msg, hdr); 366 return err; 367 } 368 369 static int vdpa_nl_cmd_mgmtdev_get_doit(struct sk_buff *skb, struct genl_info *info) 370 { 371 struct vdpa_mgmt_dev *mdev; 372 struct sk_buff *msg; 373 int err; 374 375 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 376 if (!msg) 377 return -ENOMEM; 378 379 mutex_lock(&vdpa_dev_mutex); 380 mdev = vdpa_mgmtdev_get_from_attr(info->attrs); 381 if (IS_ERR(mdev)) { 382 mutex_unlock(&vdpa_dev_mutex); 383 NL_SET_ERR_MSG_MOD(info->extack, "Fail to find the specified mgmt device"); 384 err = PTR_ERR(mdev); 385 goto out; 386 } 387 388 err = vdpa_mgmtdev_fill(mdev, msg, info->snd_portid, info->snd_seq, 0); 389 mutex_unlock(&vdpa_dev_mutex); 390 if (err) 391 goto out; 392 err = genlmsg_reply(msg, info); 393 return err; 394 395 out: 396 nlmsg_free(msg); 397 return err; 398 } 399 400 static int 401 vdpa_nl_cmd_mgmtdev_get_dumpit(struct sk_buff *msg, struct netlink_callback *cb) 402 { 403 struct vdpa_mgmt_dev *mdev; 404 int start = cb->args[0]; 405 int idx = 0; 406 int err; 407 408 mutex_lock(&vdpa_dev_mutex); 409 list_for_each_entry(mdev, &mdev_head, list) { 410 if (idx < start) { 411 idx++; 412 continue; 413 } 414 err = vdpa_mgmtdev_fill(mdev, msg, NETLINK_CB(cb->skb).portid, 415 cb->nlh->nlmsg_seq, NLM_F_MULTI); 416 if (err) 417 goto out; 418 idx++; 419 } 420 out: 421 mutex_unlock(&vdpa_dev_mutex); 422 cb->args[0] = idx; 423 return msg->len; 424 } 425 426 static int vdpa_nl_cmd_dev_add_set_doit(struct sk_buff *skb, struct genl_info *info) 427 { 428 struct vdpa_mgmt_dev *mdev; 429 const char *name; 430 int err = 0; 431 432 if (!info->attrs[VDPA_ATTR_DEV_NAME]) 433 return -EINVAL; 434 435 name = nla_data(info->attrs[VDPA_ATTR_DEV_NAME]); 436 437 mutex_lock(&vdpa_dev_mutex); 438 mdev = vdpa_mgmtdev_get_from_attr(info->attrs); 439 if (IS_ERR(mdev)) { 440 NL_SET_ERR_MSG_MOD(info->extack, "Fail to find the specified management device"); 441 err = PTR_ERR(mdev); 442 goto err; 443 } 444 445 err = mdev->ops->dev_add(mdev, name); 446 err: 447 mutex_unlock(&vdpa_dev_mutex); 448 return err; 449 } 450 451 static int vdpa_nl_cmd_dev_del_set_doit(struct sk_buff *skb, struct genl_info *info) 452 { 453 struct vdpa_mgmt_dev *mdev; 454 struct vdpa_device *vdev; 455 struct device *dev; 456 const char *name; 457 int err = 0; 458 459 if (!info->attrs[VDPA_ATTR_DEV_NAME]) 460 return -EINVAL; 461 name = nla_data(info->attrs[VDPA_ATTR_DEV_NAME]); 462 463 mutex_lock(&vdpa_dev_mutex); 464 dev = bus_find_device(&vdpa_bus, NULL, name, vdpa_name_match); 465 if (!dev) { 466 NL_SET_ERR_MSG_MOD(info->extack, "device not found"); 467 err = -ENODEV; 468 goto dev_err; 469 } 470 vdev = container_of(dev, struct vdpa_device, dev); 471 if (!vdev->mdev) { 472 NL_SET_ERR_MSG_MOD(info->extack, "Only user created device can be deleted by user"); 473 err = -EINVAL; 474 goto mdev_err; 475 } 476 mdev = vdev->mdev; 477 mdev->ops->dev_del(mdev, vdev); 478 mdev_err: 479 put_device(dev); 480 dev_err: 481 mutex_unlock(&vdpa_dev_mutex); 482 return err; 483 } 484 485 static int 486 vdpa_dev_fill(struct vdpa_device *vdev, struct sk_buff *msg, u32 portid, u32 seq, 487 int flags, struct netlink_ext_ack *extack) 488 { 489 u16 max_vq_size; 490 u32 device_id; 491 u32 vendor_id; 492 void *hdr; 493 int err; 494 495 hdr = genlmsg_put(msg, portid, seq, &vdpa_nl_family, flags, VDPA_CMD_DEV_NEW); 496 if (!hdr) 497 return -EMSGSIZE; 498 499 err = vdpa_nl_mgmtdev_handle_fill(msg, vdev->mdev); 500 if (err) 501 goto msg_err; 502 503 device_id = vdev->config->get_device_id(vdev); 504 vendor_id = vdev->config->get_vendor_id(vdev); 505 max_vq_size = vdev->config->get_vq_num_max(vdev); 506 507 err = -EMSGSIZE; 508 if (nla_put_string(msg, VDPA_ATTR_DEV_NAME, dev_name(&vdev->dev))) 509 goto msg_err; 510 if (nla_put_u32(msg, VDPA_ATTR_DEV_ID, device_id)) 511 goto msg_err; 512 if (nla_put_u32(msg, VDPA_ATTR_DEV_VENDOR_ID, vendor_id)) 513 goto msg_err; 514 if (nla_put_u32(msg, VDPA_ATTR_DEV_MAX_VQS, vdev->nvqs)) 515 goto msg_err; 516 if (nla_put_u16(msg, VDPA_ATTR_DEV_MAX_VQ_SIZE, max_vq_size)) 517 goto msg_err; 518 519 genlmsg_end(msg, hdr); 520 return 0; 521 522 msg_err: 523 genlmsg_cancel(msg, hdr); 524 return err; 525 } 526 527 static int vdpa_nl_cmd_dev_get_doit(struct sk_buff *skb, struct genl_info *info) 528 { 529 struct vdpa_device *vdev; 530 struct sk_buff *msg; 531 const char *devname; 532 struct device *dev; 533 int err; 534 535 if (!info->attrs[VDPA_ATTR_DEV_NAME]) 536 return -EINVAL; 537 devname = nla_data(info->attrs[VDPA_ATTR_DEV_NAME]); 538 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 539 if (!msg) 540 return -ENOMEM; 541 542 mutex_lock(&vdpa_dev_mutex); 543 dev = bus_find_device(&vdpa_bus, NULL, devname, vdpa_name_match); 544 if (!dev) { 545 NL_SET_ERR_MSG_MOD(info->extack, "device not found"); 546 err = -ENODEV; 547 goto err; 548 } 549 vdev = container_of(dev, struct vdpa_device, dev); 550 if (!vdev->mdev) { 551 err = -EINVAL; 552 goto mdev_err; 553 } 554 err = vdpa_dev_fill(vdev, msg, info->snd_portid, info->snd_seq, 0, info->extack); 555 if (!err) 556 err = genlmsg_reply(msg, info); 557 mdev_err: 558 put_device(dev); 559 err: 560 mutex_unlock(&vdpa_dev_mutex); 561 if (err) 562 nlmsg_free(msg); 563 return err; 564 } 565 566 struct vdpa_dev_dump_info { 567 struct sk_buff *msg; 568 struct netlink_callback *cb; 569 int start_idx; 570 int idx; 571 }; 572 573 static int vdpa_dev_dump(struct device *dev, void *data) 574 { 575 struct vdpa_device *vdev = container_of(dev, struct vdpa_device, dev); 576 struct vdpa_dev_dump_info *info = data; 577 int err; 578 579 if (!vdev->mdev) 580 return 0; 581 if (info->idx < info->start_idx) { 582 info->idx++; 583 return 0; 584 } 585 err = vdpa_dev_fill(vdev, info->msg, NETLINK_CB(info->cb->skb).portid, 586 info->cb->nlh->nlmsg_seq, NLM_F_MULTI, info->cb->extack); 587 if (err) 588 return err; 589 590 info->idx++; 591 return 0; 592 } 593 594 static int vdpa_nl_cmd_dev_get_dumpit(struct sk_buff *msg, struct netlink_callback *cb) 595 { 596 struct vdpa_dev_dump_info info; 597 598 info.msg = msg; 599 info.cb = cb; 600 info.start_idx = cb->args[0]; 601 info.idx = 0; 602 603 mutex_lock(&vdpa_dev_mutex); 604 bus_for_each_dev(&vdpa_bus, NULL, &info, vdpa_dev_dump); 605 mutex_unlock(&vdpa_dev_mutex); 606 cb->args[0] = info.idx; 607 return msg->len; 608 } 609 610 static const struct nla_policy vdpa_nl_policy[VDPA_ATTR_MAX + 1] = { 611 [VDPA_ATTR_MGMTDEV_BUS_NAME] = { .type = NLA_NUL_STRING }, 612 [VDPA_ATTR_MGMTDEV_DEV_NAME] = { .type = NLA_STRING }, 613 [VDPA_ATTR_DEV_NAME] = { .type = NLA_STRING }, 614 }; 615 616 static const struct genl_ops vdpa_nl_ops[] = { 617 { 618 .cmd = VDPA_CMD_MGMTDEV_GET, 619 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 620 .doit = vdpa_nl_cmd_mgmtdev_get_doit, 621 .dumpit = vdpa_nl_cmd_mgmtdev_get_dumpit, 622 }, 623 { 624 .cmd = VDPA_CMD_DEV_NEW, 625 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 626 .doit = vdpa_nl_cmd_dev_add_set_doit, 627 .flags = GENL_ADMIN_PERM, 628 }, 629 { 630 .cmd = VDPA_CMD_DEV_DEL, 631 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 632 .doit = vdpa_nl_cmd_dev_del_set_doit, 633 .flags = GENL_ADMIN_PERM, 634 }, 635 { 636 .cmd = VDPA_CMD_DEV_GET, 637 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 638 .doit = vdpa_nl_cmd_dev_get_doit, 639 .dumpit = vdpa_nl_cmd_dev_get_dumpit, 640 }, 641 }; 642 643 static struct genl_family vdpa_nl_family __ro_after_init = { 644 .name = VDPA_GENL_NAME, 645 .version = VDPA_GENL_VERSION, 646 .maxattr = VDPA_ATTR_MAX, 647 .policy = vdpa_nl_policy, 648 .netnsok = false, 649 .module = THIS_MODULE, 650 .ops = vdpa_nl_ops, 651 .n_ops = ARRAY_SIZE(vdpa_nl_ops), 652 }; 653 654 static int vdpa_init(void) 655 { 656 int err; 657 658 err = bus_register(&vdpa_bus); 659 if (err) 660 return err; 661 err = genl_register_family(&vdpa_nl_family); 662 if (err) 663 goto err; 664 return 0; 665 666 err: 667 bus_unregister(&vdpa_bus); 668 return err; 669 } 670 671 static void __exit vdpa_exit(void) 672 { 673 genl_unregister_family(&vdpa_nl_family); 674 bus_unregister(&vdpa_bus); 675 ida_destroy(&vdpa_index_ida); 676 } 677 core_initcall(vdpa_init); 678 module_exit(vdpa_exit); 679 680 MODULE_AUTHOR("Jason Wang <jasowang@redhat.com>"); 681 MODULE_LICENSE("GPL v2"); 682