| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Mediated virtual PCI serial host device driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * Author: Neo Jia <cjia@nvidia.com> |
|---|
| 6 | 7 | * Kirti Wankhede <kwankhede@nvidia.com> |
|---|
| 7 | 8 | * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 10 | | - * published by the Free Software Foundation. |
|---|
| 11 | | - * |
|---|
| 12 | 9 | * Sample driver that creates mdev device that simulates serial port over PCI |
|---|
| 13 | 10 | * card. |
|---|
| 14 | | - * |
|---|
| 15 | 11 | */ |
|---|
| 16 | 12 | |
|---|
| 17 | 13 | #include <linux/init.h> |
|---|
| .. | .. |
|---|
| 72 | 68 | * Global Structures |
|---|
| 73 | 69 | */ |
|---|
| 74 | 70 | |
|---|
| 75 | | -struct mtty_dev { |
|---|
| 71 | +static struct mtty_dev { |
|---|
| 76 | 72 | dev_t vd_devt; |
|---|
| 77 | 73 | struct class *vd_class; |
|---|
| 78 | 74 | struct cdev vd_cdev; |
|---|
| .. | .. |
|---|
| 88 | 84 | }; |
|---|
| 89 | 85 | |
|---|
| 90 | 86 | #if defined(DEBUG_REGS) |
|---|
| 91 | | -const char *wr_reg[] = { |
|---|
| 87 | +static const char *wr_reg[] = { |
|---|
| 92 | 88 | "TX", |
|---|
| 93 | 89 | "IER", |
|---|
| 94 | 90 | "FCR", |
|---|
| .. | .. |
|---|
| 99 | 95 | "SCR" |
|---|
| 100 | 96 | }; |
|---|
| 101 | 97 | |
|---|
| 102 | | -const char *rd_reg[] = { |
|---|
| 98 | +static const char *rd_reg[] = { |
|---|
| 103 | 99 | "RX", |
|---|
| 104 | 100 | "IER", |
|---|
| 105 | 101 | "IIR", |
|---|
| .. | .. |
|---|
| 147 | 143 | int nr_ports; |
|---|
| 148 | 144 | }; |
|---|
| 149 | 145 | |
|---|
| 150 | | -struct mutex mdev_list_lock; |
|---|
| 151 | | -struct list_head mdev_devices_list; |
|---|
| 146 | +static struct mutex mdev_list_lock; |
|---|
| 147 | +static struct list_head mdev_devices_list; |
|---|
| 152 | 148 | |
|---|
| 153 | 149 | static const struct file_operations vd_fops = { |
|---|
| 154 | 150 | .owner = THIS_MODULE, |
|---|
| .. | .. |
|---|
| 156 | 152 | |
|---|
| 157 | 153 | /* function prototypes */ |
|---|
| 158 | 154 | |
|---|
| 159 | | -static int mtty_trigger_interrupt(uuid_le uuid); |
|---|
| 155 | +static int mtty_trigger_interrupt(struct mdev_state *mdev_state); |
|---|
| 160 | 156 | |
|---|
| 161 | 157 | /* Helper functions */ |
|---|
| 162 | | -static struct mdev_state *find_mdev_state_by_uuid(uuid_le uuid) |
|---|
| 163 | | -{ |
|---|
| 164 | | - struct mdev_state *mds; |
|---|
| 165 | 158 | |
|---|
| 166 | | - list_for_each_entry(mds, &mdev_devices_list, next) { |
|---|
| 167 | | - if (uuid_le_cmp(mdev_uuid(mds->mdev), uuid) == 0) |
|---|
| 168 | | - return mds; |
|---|
| 169 | | - } |
|---|
| 170 | | - |
|---|
| 171 | | - return NULL; |
|---|
| 172 | | -} |
|---|
| 173 | | - |
|---|
| 174 | | -void dump_buffer(u8 *buf, uint32_t count) |
|---|
| 159 | +static void dump_buffer(u8 *buf, uint32_t count) |
|---|
| 175 | 160 | { |
|---|
| 176 | 161 | #if defined(DEBUG) |
|---|
| 177 | 162 | int i; |
|---|
| .. | .. |
|---|
| 341 | 326 | pr_err("Serial port %d: Fifo level trigger\n", |
|---|
| 342 | 327 | index); |
|---|
| 343 | 328 | #endif |
|---|
| 344 | | - mtty_trigger_interrupt( |
|---|
| 345 | | - mdev_uuid(mdev_state->mdev)); |
|---|
| 329 | + mtty_trigger_interrupt(mdev_state); |
|---|
| 346 | 330 | } |
|---|
| 347 | 331 | } else { |
|---|
| 348 | 332 | #if defined(DEBUG_INTR) |
|---|
| .. | .. |
|---|
| 356 | 340 | */ |
|---|
| 357 | 341 | if (mdev_state->s[index].uart_reg[UART_IER] & |
|---|
| 358 | 342 | UART_IER_RLSI) |
|---|
| 359 | | - mtty_trigger_interrupt( |
|---|
| 360 | | - mdev_uuid(mdev_state->mdev)); |
|---|
| 343 | + mtty_trigger_interrupt(mdev_state); |
|---|
| 361 | 344 | } |
|---|
| 362 | 345 | mutex_unlock(&mdev_state->rxtx_lock); |
|---|
| 363 | 346 | break; |
|---|
| .. | .. |
|---|
| 376 | 359 | pr_err("Serial port %d: IER_THRI write\n", |
|---|
| 377 | 360 | index); |
|---|
| 378 | 361 | #endif |
|---|
| 379 | | - mtty_trigger_interrupt( |
|---|
| 380 | | - mdev_uuid(mdev_state->mdev)); |
|---|
| 362 | + mtty_trigger_interrupt(mdev_state); |
|---|
| 381 | 363 | } |
|---|
| 382 | 364 | |
|---|
| 383 | 365 | mutex_unlock(&mdev_state->rxtx_lock); |
|---|
| .. | .. |
|---|
| 448 | 430 | #if defined(DEBUG_INTR) |
|---|
| 449 | 431 | pr_err("Serial port %d: MCR_OUT2 write\n", index); |
|---|
| 450 | 432 | #endif |
|---|
| 451 | | - mtty_trigger_interrupt(mdev_uuid(mdev_state->mdev)); |
|---|
| 433 | + mtty_trigger_interrupt(mdev_state); |
|---|
| 452 | 434 | } |
|---|
| 453 | 435 | |
|---|
| 454 | 436 | if ((mdev_state->s[index].uart_reg[UART_IER] & UART_IER_MSI) && |
|---|
| .. | .. |
|---|
| 456 | 438 | #if defined(DEBUG_INTR) |
|---|
| 457 | 439 | pr_err("Serial port %d: MCR RTS/DTR write\n", index); |
|---|
| 458 | 440 | #endif |
|---|
| 459 | | - mtty_trigger_interrupt(mdev_uuid(mdev_state->mdev)); |
|---|
| 441 | + mtty_trigger_interrupt(mdev_state); |
|---|
| 460 | 442 | } |
|---|
| 461 | 443 | break; |
|---|
| 462 | 444 | |
|---|
| .. | .. |
|---|
| 507 | 489 | #endif |
|---|
| 508 | 490 | if (mdev_state->s[index].uart_reg[UART_IER] & |
|---|
| 509 | 491 | UART_IER_THRI) |
|---|
| 510 | | - mtty_trigger_interrupt( |
|---|
| 511 | | - mdev_uuid(mdev_state->mdev)); |
|---|
| 492 | + mtty_trigger_interrupt(mdev_state); |
|---|
| 512 | 493 | } |
|---|
| 513 | 494 | mutex_unlock(&mdev_state->rxtx_lock); |
|---|
| 514 | 495 | |
|---|
| .. | .. |
|---|
| 727 | 708 | return ret; |
|---|
| 728 | 709 | } |
|---|
| 729 | 710 | |
|---|
| 730 | | -int mtty_create(struct kobject *kobj, struct mdev_device *mdev) |
|---|
| 711 | +static int mtty_create(struct kobject *kobj, struct mdev_device *mdev) |
|---|
| 731 | 712 | { |
|---|
| 732 | 713 | struct mdev_state *mdev_state; |
|---|
| 733 | 714 | char name[MTTY_STRING_LEN]; |
|---|
| .. | .. |
|---|
| 777 | 758 | return 0; |
|---|
| 778 | 759 | } |
|---|
| 779 | 760 | |
|---|
| 780 | | -int mtty_remove(struct mdev_device *mdev) |
|---|
| 761 | +static int mtty_remove(struct mdev_device *mdev) |
|---|
| 781 | 762 | { |
|---|
| 782 | 763 | struct mdev_state *mds, *tmp_mds; |
|---|
| 783 | 764 | struct mdev_state *mdev_state = mdev_get_drvdata(mdev); |
|---|
| .. | .. |
|---|
| 799 | 780 | return ret; |
|---|
| 800 | 781 | } |
|---|
| 801 | 782 | |
|---|
| 802 | | -int mtty_reset(struct mdev_device *mdev) |
|---|
| 783 | +static int mtty_reset(struct mdev_device *mdev) |
|---|
| 803 | 784 | { |
|---|
| 804 | 785 | struct mdev_state *mdev_state; |
|---|
| 805 | 786 | |
|---|
| .. | .. |
|---|
| 815 | 796 | return 0; |
|---|
| 816 | 797 | } |
|---|
| 817 | 798 | |
|---|
| 818 | | -ssize_t mtty_read(struct mdev_device *mdev, char __user *buf, size_t count, |
|---|
| 819 | | - loff_t *ppos) |
|---|
| 799 | +static ssize_t mtty_read(struct mdev_device *mdev, char __user *buf, |
|---|
| 800 | + size_t count, loff_t *ppos) |
|---|
| 820 | 801 | { |
|---|
| 821 | 802 | unsigned int done = 0; |
|---|
| 822 | 803 | int ret; |
|---|
| .. | .. |
|---|
| 874 | 855 | return -EFAULT; |
|---|
| 875 | 856 | } |
|---|
| 876 | 857 | |
|---|
| 877 | | -ssize_t mtty_write(struct mdev_device *mdev, const char __user *buf, |
|---|
| 858 | +static ssize_t mtty_write(struct mdev_device *mdev, const char __user *buf, |
|---|
| 878 | 859 | size_t count, loff_t *ppos) |
|---|
| 879 | 860 | { |
|---|
| 880 | 861 | unsigned int done = 0; |
|---|
| .. | .. |
|---|
| 1032 | 1013 | return ret; |
|---|
| 1033 | 1014 | } |
|---|
| 1034 | 1015 | |
|---|
| 1035 | | -static int mtty_trigger_interrupt(uuid_le uuid) |
|---|
| 1016 | +static int mtty_trigger_interrupt(struct mdev_state *mdev_state) |
|---|
| 1036 | 1017 | { |
|---|
| 1037 | 1018 | int ret = -1; |
|---|
| 1038 | | - struct mdev_state *mdev_state; |
|---|
| 1039 | | - |
|---|
| 1040 | | - mdev_state = find_mdev_state_by_uuid(uuid); |
|---|
| 1041 | | - |
|---|
| 1042 | | - if (!mdev_state) { |
|---|
| 1043 | | - pr_info("%s: mdev not found\n", __func__); |
|---|
| 1044 | | - return -EINVAL; |
|---|
| 1045 | | - } |
|---|
| 1046 | 1019 | |
|---|
| 1047 | 1020 | if ((mdev_state->irq_index == VFIO_PCI_MSI_IRQ_INDEX) && |
|---|
| 1048 | 1021 | (!mdev_state->msi_evtfd)) |
|---|
| .. | .. |
|---|
| 1067 | 1040 | return ret; |
|---|
| 1068 | 1041 | } |
|---|
| 1069 | 1042 | |
|---|
| 1070 | | -int mtty_get_region_info(struct mdev_device *mdev, |
|---|
| 1043 | +static int mtty_get_region_info(struct mdev_device *mdev, |
|---|
| 1071 | 1044 | struct vfio_region_info *region_info, |
|---|
| 1072 | 1045 | u16 *cap_type_id, void **cap_type) |
|---|
| 1073 | 1046 | { |
|---|
| .. | .. |
|---|
| 1116 | 1089 | return 0; |
|---|
| 1117 | 1090 | } |
|---|
| 1118 | 1091 | |
|---|
| 1119 | | -int mtty_get_irq_info(struct mdev_device *mdev, struct vfio_irq_info *irq_info) |
|---|
| 1092 | +static int mtty_get_irq_info(struct mdev_device *mdev, |
|---|
| 1093 | + struct vfio_irq_info *irq_info) |
|---|
| 1120 | 1094 | { |
|---|
| 1121 | 1095 | switch (irq_info->index) { |
|---|
| 1122 | 1096 | case VFIO_PCI_INTX_IRQ_INDEX: |
|---|
| .. | .. |
|---|
| 1140 | 1114 | return 0; |
|---|
| 1141 | 1115 | } |
|---|
| 1142 | 1116 | |
|---|
| 1143 | | -int mtty_get_device_info(struct mdev_device *mdev, |
|---|
| 1117 | +static int mtty_get_device_info(struct mdev_device *mdev, |
|---|
| 1144 | 1118 | struct vfio_device_info *dev_info) |
|---|
| 1145 | 1119 | { |
|---|
| 1146 | 1120 | dev_info->flags = VFIO_DEVICE_FLAGS_PCI; |
|---|
| .. | .. |
|---|
| 1272 | 1246 | return -ENOTTY; |
|---|
| 1273 | 1247 | } |
|---|
| 1274 | 1248 | |
|---|
| 1275 | | -int mtty_open(struct mdev_device *mdev) |
|---|
| 1249 | +static int mtty_open(struct mdev_device *mdev) |
|---|
| 1276 | 1250 | { |
|---|
| 1277 | 1251 | pr_info("%s\n", __func__); |
|---|
| 1278 | 1252 | return 0; |
|---|
| 1279 | 1253 | } |
|---|
| 1280 | 1254 | |
|---|
| 1281 | | -void mtty_close(struct mdev_device *mdev) |
|---|
| 1255 | +static void mtty_close(struct mdev_device *mdev) |
|---|
| 1282 | 1256 | { |
|---|
| 1283 | 1257 | pr_info("%s\n", __func__); |
|---|
| 1284 | 1258 | } |
|---|
| .. | .. |
|---|
| 1302 | 1276 | .attrs = mtty_dev_attrs, |
|---|
| 1303 | 1277 | }; |
|---|
| 1304 | 1278 | |
|---|
| 1305 | | -const struct attribute_group *mtty_dev_groups[] = { |
|---|
| 1279 | +static const struct attribute_group *mtty_dev_groups[] = { |
|---|
| 1306 | 1280 | &mtty_dev_group, |
|---|
| 1307 | 1281 | NULL, |
|---|
| 1308 | 1282 | }; |
|---|
| .. | .. |
|---|
| 1329 | 1303 | .attrs = mdev_dev_attrs, |
|---|
| 1330 | 1304 | }; |
|---|
| 1331 | 1305 | |
|---|
| 1332 | | -const struct attribute_group *mdev_dev_groups[] = { |
|---|
| 1306 | +static const struct attribute_group *mdev_dev_groups[] = { |
|---|
| 1333 | 1307 | &mdev_dev_group, |
|---|
| 1334 | 1308 | NULL, |
|---|
| 1335 | 1309 | }; |
|---|
| .. | .. |
|---|
| 1351 | 1325 | return -EINVAL; |
|---|
| 1352 | 1326 | } |
|---|
| 1353 | 1327 | |
|---|
| 1354 | | -MDEV_TYPE_ATTR_RO(name); |
|---|
| 1328 | +static MDEV_TYPE_ATTR_RO(name); |
|---|
| 1355 | 1329 | |
|---|
| 1356 | 1330 | static ssize_t |
|---|
| 1357 | 1331 | available_instances_show(struct kobject *kobj, struct device *dev, char *buf) |
|---|
| .. | .. |
|---|
| 1379 | 1353 | return sprintf(buf, "%d\n", (MAX_MTTYS - used)/ports); |
|---|
| 1380 | 1354 | } |
|---|
| 1381 | 1355 | |
|---|
| 1382 | | -MDEV_TYPE_ATTR_RO(available_instances); |
|---|
| 1356 | +static MDEV_TYPE_ATTR_RO(available_instances); |
|---|
| 1383 | 1357 | |
|---|
| 1384 | 1358 | |
|---|
| 1385 | 1359 | static ssize_t device_api_show(struct kobject *kobj, struct device *dev, |
|---|
| .. | .. |
|---|
| 1388 | 1362 | return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING); |
|---|
| 1389 | 1363 | } |
|---|
| 1390 | 1364 | |
|---|
| 1391 | | -MDEV_TYPE_ATTR_RO(device_api); |
|---|
| 1365 | +static MDEV_TYPE_ATTR_RO(device_api); |
|---|
| 1392 | 1366 | |
|---|
| 1393 | 1367 | static struct attribute *mdev_types_attrs[] = { |
|---|
| 1394 | 1368 | &mdev_type_attr_name.attr, |
|---|
| .. | .. |
|---|
| 1407 | 1381 | .attrs = mdev_types_attrs, |
|---|
| 1408 | 1382 | }; |
|---|
| 1409 | 1383 | |
|---|
| 1410 | | -struct attribute_group *mdev_type_groups[] = { |
|---|
| 1384 | +static struct attribute_group *mdev_type_groups[] = { |
|---|
| 1411 | 1385 | &mdev_type_group1, |
|---|
| 1412 | 1386 | &mdev_type_group2, |
|---|
| 1413 | 1387 | NULL, |
|---|
| .. | .. |
|---|
| 1442 | 1416 | |
|---|
| 1443 | 1417 | idr_init(&mtty_dev.vd_idr); |
|---|
| 1444 | 1418 | |
|---|
| 1445 | | - ret = alloc_chrdev_region(&mtty_dev.vd_devt, 0, MINORMASK, MTTY_NAME); |
|---|
| 1419 | + ret = alloc_chrdev_region(&mtty_dev.vd_devt, 0, MINORMASK + 1, |
|---|
| 1420 | + MTTY_NAME); |
|---|
| 1446 | 1421 | |
|---|
| 1447 | 1422 | if (ret < 0) { |
|---|
| 1448 | 1423 | pr_err("Error: failed to register mtty_dev, err:%d\n", ret); |
|---|
| .. | .. |
|---|
| 1450 | 1425 | } |
|---|
| 1451 | 1426 | |
|---|
| 1452 | 1427 | cdev_init(&mtty_dev.vd_cdev, &vd_fops); |
|---|
| 1453 | | - cdev_add(&mtty_dev.vd_cdev, mtty_dev.vd_devt, MINORMASK); |
|---|
| 1428 | + cdev_add(&mtty_dev.vd_cdev, mtty_dev.vd_devt, MINORMASK + 1); |
|---|
| 1454 | 1429 | |
|---|
| 1455 | 1430 | pr_info("major_number:%d\n", MAJOR(mtty_dev.vd_devt)); |
|---|
| 1456 | 1431 | |
|---|
| .. | .. |
|---|
| 1487 | 1462 | |
|---|
| 1488 | 1463 | failed1: |
|---|
| 1489 | 1464 | cdev_del(&mtty_dev.vd_cdev); |
|---|
| 1490 | | - unregister_chrdev_region(mtty_dev.vd_devt, MINORMASK); |
|---|
| 1465 | + unregister_chrdev_region(mtty_dev.vd_devt, MINORMASK + 1); |
|---|
| 1491 | 1466 | |
|---|
| 1492 | 1467 | all_done: |
|---|
| 1493 | 1468 | return ret; |
|---|
| .. | .. |
|---|
| 1501 | 1476 | device_unregister(&mtty_dev.dev); |
|---|
| 1502 | 1477 | idr_destroy(&mtty_dev.vd_idr); |
|---|
| 1503 | 1478 | cdev_del(&mtty_dev.vd_cdev); |
|---|
| 1504 | | - unregister_chrdev_region(mtty_dev.vd_devt, MINORMASK); |
|---|
| 1479 | + unregister_chrdev_region(mtty_dev.vd_devt, MINORMASK + 1); |
|---|
| 1505 | 1480 | class_destroy(mtty_dev.vd_class); |
|---|
| 1506 | 1481 | mtty_dev.vd_class = NULL; |
|---|
| 1507 | 1482 | pr_info("mtty_dev: Unloaded!\n"); |
|---|