~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/virt/lib/irqbypass.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /virt/lib/irqbypass.c (Version linux-6.12-rc7) and /virt/lib/irqbypass.c (Version linux-4.20.17)


  1 // SPDX-License-Identifier: GPL-2.0-only       << 
  2 /*                                                  1 /*
  3  * IRQ offload/bypass manager                       2  * IRQ offload/bypass manager
  4  *                                                  3  *
  5  * Copyright (C) 2015 Red Hat, Inc.                 4  * Copyright (C) 2015 Red Hat, Inc.
  6  * Copyright (c) 2015 Linaro Ltd.                   5  * Copyright (c) 2015 Linaro Ltd.
  7  *                                                  6  *
                                                   >>   7  * This program is free software; you can redistribute it and/or modify
                                                   >>   8  * it under the terms of the GNU General Public License version 2 as
                                                   >>   9  * published by the Free Software Foundation.
                                                   >>  10  *
  8  * Various virtualization hardware acceleratio     11  * Various virtualization hardware acceleration techniques allow bypassing or
  9  * offloading interrupts received from devices     12  * offloading interrupts received from devices around the host kernel.  Posted
 10  * Interrupts on Intel VT-d systems can allow      13  * Interrupts on Intel VT-d systems can allow interrupts to be received
 11  * directly by a virtual machine.  ARM IRQ For     14  * directly by a virtual machine.  ARM IRQ Forwarding allows forwarded physical
 12  * interrupts to be directly deactivated by th     15  * interrupts to be directly deactivated by the guest.  This manager allows
 13  * interrupt producers and consumers to find e     16  * interrupt producers and consumers to find each other to enable this sort of
 14  * bypass.                                         17  * bypass.
 15  */                                                18  */
 16                                                    19 
 17 #include <linux/irqbypass.h>                       20 #include <linux/irqbypass.h>
 18 #include <linux/list.h>                            21 #include <linux/list.h>
 19 #include <linux/module.h>                          22 #include <linux/module.h>
 20 #include <linux/mutex.h>                           23 #include <linux/mutex.h>
 21                                                    24 
 22 MODULE_LICENSE("GPL v2");                          25 MODULE_LICENSE("GPL v2");
 23 MODULE_DESCRIPTION("IRQ bypass manager utility     26 MODULE_DESCRIPTION("IRQ bypass manager utility module");
 24                                                    27 
 25 static LIST_HEAD(producers);                       28 static LIST_HEAD(producers);
 26 static LIST_HEAD(consumers);                       29 static LIST_HEAD(consumers);
 27 static DEFINE_MUTEX(lock);                         30 static DEFINE_MUTEX(lock);
 28                                                    31 
 29 /* @lock must be held when calling connect */      32 /* @lock must be held when calling connect */
 30 static int __connect(struct irq_bypass_produce     33 static int __connect(struct irq_bypass_producer *prod,
 31                      struct irq_bypass_consume     34                      struct irq_bypass_consumer *cons)
 32 {                                                  35 {
 33         int ret = 0;                               36         int ret = 0;
 34                                                    37 
 35         if (prod->stop)                            38         if (prod->stop)
 36                 prod->stop(prod);                  39                 prod->stop(prod);
 37         if (cons->stop)                            40         if (cons->stop)
 38                 cons->stop(cons);                  41                 cons->stop(cons);
 39                                                    42 
 40         if (prod->add_consumer)                    43         if (prod->add_consumer)
 41                 ret = prod->add_consumer(prod,     44                 ret = prod->add_consumer(prod, cons);
 42                                                    45 
 43         if (!ret) {                                46         if (!ret) {
 44                 ret = cons->add_producer(cons,     47                 ret = cons->add_producer(cons, prod);
 45                 if (ret && prod->del_consumer)     48                 if (ret && prod->del_consumer)
 46                         prod->del_consumer(pro     49                         prod->del_consumer(prod, cons);
 47         }                                          50         }
 48                                                    51 
 49         if (cons->start)                           52         if (cons->start)
 50                 cons->start(cons);                 53                 cons->start(cons);
 51         if (prod->start)                           54         if (prod->start)
 52                 prod->start(prod);                 55                 prod->start(prod);
 53                                                    56 
 54         return ret;                                57         return ret;
 55 }                                                  58 }
 56                                                    59 
 57 /* @lock must be held when calling disconnect      60 /* @lock must be held when calling disconnect */
 58 static void __disconnect(struct irq_bypass_pro     61 static void __disconnect(struct irq_bypass_producer *prod,
 59                          struct irq_bypass_con     62                          struct irq_bypass_consumer *cons)
 60 {                                                  63 {
 61         if (prod->stop)                            64         if (prod->stop)
 62                 prod->stop(prod);                  65                 prod->stop(prod);
 63         if (cons->stop)                            66         if (cons->stop)
 64                 cons->stop(cons);                  67                 cons->stop(cons);
 65                                                    68 
 66         cons->del_producer(cons, prod);            69         cons->del_producer(cons, prod);
 67                                                    70 
 68         if (prod->del_consumer)                    71         if (prod->del_consumer)
 69                 prod->del_consumer(prod, cons)     72                 prod->del_consumer(prod, cons);
 70                                                    73 
 71         if (cons->start)                           74         if (cons->start)
 72                 cons->start(cons);                 75                 cons->start(cons);
 73         if (prod->start)                           76         if (prod->start)
 74                 prod->start(prod);                 77                 prod->start(prod);
 75 }                                                  78 }
 76                                                    79 
 77 /**                                                80 /**
 78  * irq_bypass_register_producer - register IRQ     81  * irq_bypass_register_producer - register IRQ bypass producer
 79  * @producer: pointer to producer structure        82  * @producer: pointer to producer structure
 80  *                                                 83  *
 81  * Add the provided IRQ producer to the list o     84  * Add the provided IRQ producer to the list of producers and connect
 82  * with any matching token found on the IRQ co     85  * with any matching token found on the IRQ consumers list.
 83  */                                                86  */
 84 int irq_bypass_register_producer(struct irq_by     87 int irq_bypass_register_producer(struct irq_bypass_producer *producer)
 85 {                                                  88 {
 86         struct irq_bypass_producer *tmp;           89         struct irq_bypass_producer *tmp;
 87         struct irq_bypass_consumer *consumer;      90         struct irq_bypass_consumer *consumer;
 88         int ret;                               << 
 89                                                    91 
 90         if (!producer->token)                      92         if (!producer->token)
 91                 return -EINVAL;                    93                 return -EINVAL;
 92                                                    94 
 93         might_sleep();                             95         might_sleep();
 94                                                    96 
 95         if (!try_module_get(THIS_MODULE))          97         if (!try_module_get(THIS_MODULE))
 96                 return -ENODEV;                    98                 return -ENODEV;
 97                                                    99 
 98         mutex_lock(&lock);                        100         mutex_lock(&lock);
 99                                                   101 
100         list_for_each_entry(tmp, &producers, n    102         list_for_each_entry(tmp, &producers, node) {
101                 if (tmp->token == producer->to    103                 if (tmp->token == producer->token) {
102                         ret = -EBUSY;          !! 104                         mutex_unlock(&lock);
103                         goto out_err;          !! 105                         module_put(THIS_MODULE);
                                                   >> 106                         return -EBUSY;
104                 }                                 107                 }
105         }                                         108         }
106                                                   109 
107         list_for_each_entry(consumer, &consume    110         list_for_each_entry(consumer, &consumers, node) {
108                 if (consumer->token == produce    111                 if (consumer->token == producer->token) {
109                         ret = __connect(produc !! 112                         int ret = __connect(producer, consumer);
110                         if (ret)               !! 113                         if (ret) {
111                                 goto out_err;  !! 114                                 mutex_unlock(&lock);
                                                   >> 115                                 module_put(THIS_MODULE);
                                                   >> 116                                 return ret;
                                                   >> 117                         }
112                         break;                    118                         break;
113                 }                                 119                 }
114         }                                         120         }
115                                                   121 
116         list_add(&producer->node, &producers);    122         list_add(&producer->node, &producers);
117                                                   123 
118         mutex_unlock(&lock);                      124         mutex_unlock(&lock);
119                                                   125 
120         return 0;                                 126         return 0;
121 out_err:                                       << 
122         mutex_unlock(&lock);                   << 
123         module_put(THIS_MODULE);               << 
124         return ret;                            << 
125 }                                                 127 }
126 EXPORT_SYMBOL_GPL(irq_bypass_register_producer    128 EXPORT_SYMBOL_GPL(irq_bypass_register_producer);
127                                                   129 
128 /**                                               130 /**
129  * irq_bypass_unregister_producer - unregister    131  * irq_bypass_unregister_producer - unregister IRQ bypass producer
130  * @producer: pointer to producer structure       132  * @producer: pointer to producer structure
131  *                                                133  *
132  * Remove a previously registered IRQ producer    134  * Remove a previously registered IRQ producer from the list of producers
133  * and disconnect it from any connected IRQ co    135  * and disconnect it from any connected IRQ consumer.
134  */                                               136  */
135 void irq_bypass_unregister_producer(struct irq    137 void irq_bypass_unregister_producer(struct irq_bypass_producer *producer)
136 {                                                 138 {
137         struct irq_bypass_producer *tmp;          139         struct irq_bypass_producer *tmp;
138         struct irq_bypass_consumer *consumer;     140         struct irq_bypass_consumer *consumer;
139                                                   141 
140         if (!producer->token)                     142         if (!producer->token)
141                 return;                           143                 return;
142                                                   144 
143         might_sleep();                            145         might_sleep();
144                                                   146 
145         if (!try_module_get(THIS_MODULE))         147         if (!try_module_get(THIS_MODULE))
146                 return; /* nothing in the list    148                 return; /* nothing in the list anyway */
147                                                   149 
148         mutex_lock(&lock);                        150         mutex_lock(&lock);
149                                                   151 
150         list_for_each_entry(tmp, &producers, n    152         list_for_each_entry(tmp, &producers, node) {
151                 if (tmp->token != producer->to    153                 if (tmp->token != producer->token)
152                         continue;                 154                         continue;
153                                                   155 
154                 list_for_each_entry(consumer,     156                 list_for_each_entry(consumer, &consumers, node) {
155                         if (consumer->token ==    157                         if (consumer->token == producer->token) {
156                                 __disconnect(p    158                                 __disconnect(producer, consumer);
157                                 break;            159                                 break;
158                         }                         160                         }
159                 }                                 161                 }
160                                                   162 
161                 list_del(&producer->node);        163                 list_del(&producer->node);
162                 module_put(THIS_MODULE);          164                 module_put(THIS_MODULE);
163                 break;                            165                 break;
164         }                                         166         }
165                                                   167 
166         mutex_unlock(&lock);                      168         mutex_unlock(&lock);
167                                                   169 
168         module_put(THIS_MODULE);                  170         module_put(THIS_MODULE);
169 }                                                 171 }
170 EXPORT_SYMBOL_GPL(irq_bypass_unregister_produc    172 EXPORT_SYMBOL_GPL(irq_bypass_unregister_producer);
171                                                   173 
172 /**                                               174 /**
173  * irq_bypass_register_consumer - register IRQ    175  * irq_bypass_register_consumer - register IRQ bypass consumer
174  * @consumer: pointer to consumer structure       176  * @consumer: pointer to consumer structure
175  *                                                177  *
176  * Add the provided IRQ consumer to the list o    178  * Add the provided IRQ consumer to the list of consumers and connect
177  * with any matching token found on the IRQ pr    179  * with any matching token found on the IRQ producer list.
178  */                                               180  */
179 int irq_bypass_register_consumer(struct irq_by    181 int irq_bypass_register_consumer(struct irq_bypass_consumer *consumer)
180 {                                                 182 {
181         struct irq_bypass_consumer *tmp;          183         struct irq_bypass_consumer *tmp;
182         struct irq_bypass_producer *producer;     184         struct irq_bypass_producer *producer;
183         int ret;                               << 
184                                                   185 
185         if (!consumer->token ||                   186         if (!consumer->token ||
186             !consumer->add_producer || !consum    187             !consumer->add_producer || !consumer->del_producer)
187                 return -EINVAL;                   188                 return -EINVAL;
188                                                   189 
189         might_sleep();                            190         might_sleep();
190                                                   191 
191         if (!try_module_get(THIS_MODULE))         192         if (!try_module_get(THIS_MODULE))
192                 return -ENODEV;                   193                 return -ENODEV;
193                                                   194 
194         mutex_lock(&lock);                        195         mutex_lock(&lock);
195                                                   196 
196         list_for_each_entry(tmp, &consumers, n    197         list_for_each_entry(tmp, &consumers, node) {
197                 if (tmp->token == consumer->to    198                 if (tmp->token == consumer->token || tmp == consumer) {
198                         ret = -EBUSY;          !! 199                         mutex_unlock(&lock);
199                         goto out_err;          !! 200                         module_put(THIS_MODULE);
                                                   >> 201                         return -EBUSY;
200                 }                                 202                 }
201         }                                         203         }
202                                                   204 
203         list_for_each_entry(producer, &produce    205         list_for_each_entry(producer, &producers, node) {
204                 if (producer->token == consume    206                 if (producer->token == consumer->token) {
205                         ret = __connect(produc !! 207                         int ret = __connect(producer, consumer);
206                         if (ret)               !! 208                         if (ret) {
207                                 goto out_err;  !! 209                                 mutex_unlock(&lock);
                                                   >> 210                                 module_put(THIS_MODULE);
                                                   >> 211                                 return ret;
                                                   >> 212                         }
208                         break;                    213                         break;
209                 }                                 214                 }
210         }                                         215         }
211                                                   216 
212         list_add(&consumer->node, &consumers);    217         list_add(&consumer->node, &consumers);
213                                                   218 
214         mutex_unlock(&lock);                      219         mutex_unlock(&lock);
215                                                   220 
216         return 0;                                 221         return 0;
217 out_err:                                       << 
218         mutex_unlock(&lock);                   << 
219         module_put(THIS_MODULE);               << 
220         return ret;                            << 
221 }                                                 222 }
222 EXPORT_SYMBOL_GPL(irq_bypass_register_consumer    223 EXPORT_SYMBOL_GPL(irq_bypass_register_consumer);
223                                                   224 
224 /**                                               225 /**
225  * irq_bypass_unregister_consumer - unregister    226  * irq_bypass_unregister_consumer - unregister IRQ bypass consumer
226  * @consumer: pointer to consumer structure       227  * @consumer: pointer to consumer structure
227  *                                                228  *
228  * Remove a previously registered IRQ consumer    229  * Remove a previously registered IRQ consumer from the list of consumers
229  * and disconnect it from any connected IRQ pr    230  * and disconnect it from any connected IRQ producer.
230  */                                               231  */
231 void irq_bypass_unregister_consumer(struct irq    232 void irq_bypass_unregister_consumer(struct irq_bypass_consumer *consumer)
232 {                                                 233 {
233         struct irq_bypass_consumer *tmp;          234         struct irq_bypass_consumer *tmp;
234         struct irq_bypass_producer *producer;     235         struct irq_bypass_producer *producer;
235                                                   236 
236         if (!consumer->token)                     237         if (!consumer->token)
237                 return;                           238                 return;
238                                                   239 
239         might_sleep();                            240         might_sleep();
240                                                   241 
241         if (!try_module_get(THIS_MODULE))         242         if (!try_module_get(THIS_MODULE))
242                 return; /* nothing in the list    243                 return; /* nothing in the list anyway */
243                                                   244 
244         mutex_lock(&lock);                        245         mutex_lock(&lock);
245                                                   246 
246         list_for_each_entry(tmp, &consumers, n    247         list_for_each_entry(tmp, &consumers, node) {
247                 if (tmp != consumer)              248                 if (tmp != consumer)
248                         continue;                 249                         continue;
249                                                   250 
250                 list_for_each_entry(producer,     251                 list_for_each_entry(producer, &producers, node) {
251                         if (producer->token ==    252                         if (producer->token == consumer->token) {
252                                 __disconnect(p    253                                 __disconnect(producer, consumer);
253                                 break;            254                                 break;
254                         }                         255                         }
255                 }                                 256                 }
256                                                   257 
257                 list_del(&consumer->node);        258                 list_del(&consumer->node);
258                 module_put(THIS_MODULE);          259                 module_put(THIS_MODULE);
259                 break;                            260                 break;
260         }                                         261         }
261                                                   262 
262         mutex_unlock(&lock);                      263         mutex_unlock(&lock);
263                                                   264 
264         module_put(THIS_MODULE);                  265         module_put(THIS_MODULE);
265 }                                                 266 }
266 EXPORT_SYMBOL_GPL(irq_bypass_unregister_consum    267 EXPORT_SYMBOL_GPL(irq_bypass_unregister_consumer);
267                                                   268 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php