1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/types.h>
3 #include <linux/mm.h>
4 #include <linux/slab.h>
5 #include <linux/idr.h>
6 #include <asm/mshyperv.h>
7
8 #include "mshv.h"
9 #include "mshv_root.h"
10
11 /*
12 * Ports and connections are hypervisor struct used for inter-partition
13 * communication. Port represents the source and connection represents
14 * the destination. Partitions are responsible for managing the port and
15 * connection ids.
16 *
17 */
18
19 #define PORTID_MIN 1
20 #define PORTID_MAX INT_MAX
21
22 static DEFINE_IDR(port_table_idr);
23
24 void
mshv_port_table_fini(void)25 mshv_port_table_fini(void)
26 {
27 struct port_table_info *port_info;
28 unsigned long i, tmp;
29
30 idr_lock(&port_table_idr);
31 if (!idr_is_empty(&port_table_idr)) {
32 idr_for_each_entry_ul(&port_table_idr, port_info, tmp, i) {
33 port_info = idr_remove(&port_table_idr, i);
34 kfree_rcu(port_info, portbl_rcu);
35 }
36 }
37 idr_unlock(&port_table_idr);
38 }
39
40 int
mshv_portid_alloc(struct port_table_info * info)41 mshv_portid_alloc(struct port_table_info *info)
42 {
43 int ret = 0;
44
45 idr_lock(&port_table_idr);
46 ret = idr_alloc(&port_table_idr, info, PORTID_MIN,
47 PORTID_MAX, GFP_KERNEL);
48 idr_unlock(&port_table_idr);
49
50 return ret;
51 }
52
53 void
mshv_portid_free(int port_id)54 mshv_portid_free(int port_id)
55 {
56 struct port_table_info *info;
57
58 idr_lock(&port_table_idr);
59 info = idr_remove(&port_table_idr, port_id);
60 WARN_ON(!info);
61 idr_unlock(&port_table_idr);
62
63 synchronize_rcu();
64 kfree(info);
65 }
66
67 int
mshv_portid_lookup(int port_id,struct port_table_info * info)68 mshv_portid_lookup(int port_id, struct port_table_info *info)
69 {
70 struct port_table_info *_info;
71 int ret = -ENOENT;
72
73 rcu_read_lock();
74 _info = idr_find(&port_table_idr, port_id);
75 rcu_read_unlock();
76
77 if (_info) {
78 *info = *_info;
79 ret = 0;
80 }
81
82 return ret;
83 }
84