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; 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 55 void 56 mshv_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 68 int 69 mshv_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 } 85