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 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 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 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 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