.. | .. |
---|
| 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"); |
---|