projects/linux·blob master · refs

84 lines · 1.6 KiB

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
22static DEFINE_IDR(port_table_idr);
23
24void
25mshv_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
40int
41mshv_portid_alloc(struct port_table_info *info)
42{
43 int ret;
44
45 idr_preload(GFP_KERNEL);
46 idr_lock(&port_table_idr);
47 ret = idr_alloc(&port_table_idr, info, PORTID_MIN,
48 PORTID_MAX, GFP_NOWAIT);
49 idr_unlock(&port_table_idr);
50 idr_preload_end();
51
52 return ret;
53}
54
55void
56mshv_portid_free(int port_id)
57{
58 struct port_table_info *info;
59
60 idr_lock(&port_table_idr);
61 info = idr_remove(&port_table_idr, port_id);
62 WARN_ON(!info);
63 idr_unlock(&port_table_idr);
64
65 kfree_rcu(info, portbl_rcu);
66}
67
68int
69mshv_portid_lookup(int port_id, struct port_table_info *info)
70{
71 struct port_table_info *_info;
72 int ret = -ENOENT;
73
74 rcu_read_lock();
75 _info = idr_find(&port_table_idr, port_id);
76 rcu_read_unlock();
77
78 if (_info) {
79 *info = *_info;
80 ret = 0;
81 }
82
83 return ret;
84}