Changeset 4d76cfc in mainline
- Timestamp:
- 2017-08-19T00:01:04Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e7c4115d
- Parents:
- 24abb85d
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ddi/irq.c
r24abb85d r4d76cfc 32 32 /** 33 33 * @file 34 * @brief IRQ dispatcher. 35 * 36 * This file provides means of connecting IRQs with particular devices and logic 37 * for dispatching interrupts to IRQ handlers defined by those devices. 38 * 39 * This code is designed to support: 40 * - multiple devices sharing single IRQ 41 * - multiple IRQs per single device 42 * - multiple instances of the same device 43 * 44 * 45 * Note about architectures. 46 * 47 * Some architectures have the term IRQ well defined. Examples of such 48 * architectures include amd64, ia32 and mips32. Some other architectures, such 49 * as sparc64, don't use the term at all. In those cases, we boldly step forward 50 * and define what an IRQ is. 51 * 52 * The implementation is generic enough and still allows the architectures to 53 * use the hardware layout effectively. For instance, on amd64 and ia32, where 54 * there is only 16 IRQs, the irq_hash_table can be optimized to a 55 * one-dimensional array. Next, when it is known that the IRQ numbers (aka 56 * INR's) are unique, the claim functions can always return IRQ_ACCEPT. 57 * 58 * 59 * Note about the irq_hash_table. 60 * 61 * The hash table is configured to use two keys: inr and mode. However, the 62 * hash index is computed only from inr. Moreover, if mode is IRQ_HT_MODE_CLAIM, 63 * the match is based also on the return value of the claim(). Otherwise the 64 * the keys do not match. 34 * @brief IRQ dispatcher 35 * 36 * This file provides means of connecting IRQs with respective device drivers 37 * and logic for dispatching interrupts to IRQ handlers defined by those 38 * drivers. 65 39 */ 66 40 … … 75 49 #include <arch.h> 76 50 77 /** Spinlock protecting the kernel IRQ hash table .51 /** Spinlock protecting the kernel IRQ hash table 78 52 * 79 53 * This lock must be taken only when interrupts are disabled. … … 85 59 static hash_table_t irq_kernel_hash_table; 86 60 87 /** Spinlock protecting the uspace IRQ hash table .61 /** Spinlock protecting the uspace IRQ hash table 88 62 * 89 63 * This lock must be taken only when interrupts are disabled. … … 92 66 IRQ_SPINLOCK_INITIALIZE(irq_uspace_hash_table_lock); 93 67 94 /** The uspace IRQ hash table .*/68 /** The uspace IRQ hash table */ 95 69 hash_table_t irq_uspace_hash_table; 96 70 97 /**98 * Hash table operations for cases when we know that there will be collisions99 * between different keys.100 */101 71 static size_t irq_ht_hash(sysarg_t *key); 102 72 static bool irq_ht_compare(sysarg_t *key, size_t keys, link_t *item); … … 109 79 }; 110 80 111 /** 112 * Hash table operations for cases when we know that there will be no collisions 113 * between different keys. However, there might be still collisions among 114 * elements with single key (sharing of one IRQ). 115 */ 116 static size_t irq_lin_hash(sysarg_t *key); 117 static bool irq_lin_compare(sysarg_t *key, size_t keys, link_t *item); 118 static void irq_lin_remove(link_t *item); 119 120 static hash_table_operations_t irq_lin_ops = { 121 .hash = irq_lin_hash, 122 .compare = irq_lin_compare, 123 .remove_callback = irq_lin_remove, 124 }; 125 126 /** Number of buckets in either of the hash tables. */ 81 /** Number of buckets in either of the hash tables */ 127 82 static size_t buckets; 128 83 129 /** Last valid INR .*/84 /** Last valid INR */ 130 85 inr_t last_inr = 0; 131 86 132 /** Initialize IRQ subsystem .133 * 134 * @param inrs Numbers of unique IRQ numbers or INRs.135 * @param chains Number of chains in the hash table.87 /** Initialize IRQ subsystem 88 * 89 * @param inrs Numbers of unique IRQ numbers or INRs. 90 * @param chains Number of buckets in the hash table. 136 91 * 137 92 */ … … 141 96 last_inr = inrs - 1; 142 97 143 /* 144 * Be smart about the choice of the hash table operations. In cases in 145 * which inrs equals the requested number of chains (i.e. where there is 146 * no collision between different keys), we can use optimized set of 147 * operations. 148 */ 149 if (inrs == chains) { 150 hash_table_create(&irq_uspace_hash_table, chains, 2, 151 &irq_lin_ops); 152 hash_table_create(&irq_kernel_hash_table, chains, 2, 153 &irq_lin_ops); 154 } else { 155 hash_table_create(&irq_uspace_hash_table, chains, 2, 156 &irq_ht_ops); 157 hash_table_create(&irq_kernel_hash_table, chains, 2, 158 &irq_ht_ops); 159 } 160 } 161 162 /** Initialize one IRQ structure. 163 * 164 * @param irq Pointer to the IRQ structure to be initialized. 98 hash_table_create(&irq_uspace_hash_table, chains, 2, &irq_ht_ops); 99 hash_table_create(&irq_kernel_hash_table, chains, 2, &irq_ht_ops); 100 } 101 102 /** Initialize one IRQ structure 103 * 104 * @param irq Pointer to the IRQ structure to be initialized. 165 105 * 166 106 */ … … 176 116 } 177 117 178 /** Register IRQ for device .118 /** Register IRQ for device 179 119 * 180 120 * The irq structure must be filled with information about the interrupt source 181 121 * and with the claim() function pointer and handler() function pointer. 182 122 * 183 * @param irq IRQ structure belonging to a device.123 * @param irq IRQ structure belonging to a device. 184 124 * 185 125 */ … … 198 138 } 199 139 200 /** Search and lock the uspace IRQ hash table. 201 * 202 */ 140 /** Search and lock the uspace IRQ hash table */ 203 141 static irq_t *irq_dispatch_and_lock_uspace(inr_t inr) 204 142 { … … 221 159 } 222 160 223 /** Search and lock the kernel IRQ hash table. 224 * 225 */ 161 /** Search and lock the kernel IRQ hash table */ 226 162 static irq_t *irq_dispatch_and_lock_kernel(inr_t inr) 227 163 { … … 244 180 } 245 181 246 /** Dispatch the IRQ .182 /** Dispatch the IRQ 247 183 * 248 184 * We assume this function is only called from interrupt context (i.e. that … … 252 188 * return with interrupts disabled and holding the respective structure. 253 189 * 254 * @param inr Interrupt number (aka inr or irq).190 * @param inr Interrupt number (aka inr or irq). 255 191 * 256 192 * @return IRQ structure of the respective device … … 282 218 } 283 219 284 /** Compute hash index for the key. 285 * 286 * This function computes hash index into the IRQ hash table for which there can 287 * be collisions between different INRs. 288 * 289 * The mode is not used to compute the hash. 290 * 291 * @param key The first of the keys is inr and the second is mode. 220 /** Compute hash index for the key 221 * 222 * @param key The first of the keys is inr and the second is mode. Only inr is 223 * used to compute the hash. 292 224 * 293 225 * @return Index into the hash table. … … 300 232 } 301 233 302 /** Compare hash table element with a key. 303 * 304 * There are two things to note about this function. First, it is used for the 305 * more complex architecture setup in which there are way too many interrupt 306 * numbers (i.e. inr's) to arrange the hash table so that collisions occur only 307 * among same inrs of different devices. So the explicit check for inr match 308 * must be done. Second, if mode is IRQ_HT_MODE_CLAIM, the result of the 309 * claim() function is used for the match. Otherwise the key does not match. 234 /** Compare hash table element with a key 235 * 236 * If mode is IRQ_HT_MODE_CLAIM, the result of the claim() function is used for 237 * the match. Otherwise the key does not match. 310 238 * 311 239 * This function assumes interrupts are already disabled. 312 240 * 313 * @param key Keys (i.e. inr and mode).314 * @param keys This is 2.315 * @param item The item to compare the key with.316 * 317 * @return true on match318 * @return false on no match241 * @param key Keys (i.e. inr and mode). 242 * @param keys This is 2. 243 * @param item The item to compare the key with. 244 * 245 * @return True on match 246 * @return False on no match 319 247 * 320 248 */ … … 343 271 } 344 272 345 /** Unlock IRQ structure after hash_table_remove() .346 * 347 * @param lnk Link in the removed and locked IRQ structure.273 /** Unlock IRQ structure after hash_table_remove() 274 * 275 * @param lnk Link in the removed and locked IRQ structure. 348 276 */ 349 277 void irq_ht_remove(link_t *lnk) … … 354 282 } 355 283 356 /** Compute hash index for the key.357 *358 * This function computes hash index into the IRQ hash table for which there are359 * no collisions between different INRs.360 *361 * @param key The first of the keys is inr and the second is mode.362 *363 * @return Index into the hash table.364 *365 */366 size_t irq_lin_hash(sysarg_t key[])367 {368 inr_t inr = (inr_t) key[IRQ_HT_KEY_INR];369 return inr;370 }371 372 /** Compare hash table element with a key.373 *374 * There are two things to note about this function. First, it is used for the375 * less complex architecture setup in which there are not too many interrupt376 * numbers (i.e. inr's) to arrange the hash table so that collisions occur only377 * among same inrs of different devnos. So the explicit check for inr match is378 * not done. Second, if devno is -1, the second key (i.e. devno) is not used379 * for the match and the result of the claim() function is used instead.380 *381 * This function assumes interrupts are already disabled.382 *383 * @param key Keys (i.e. inr and mode).384 * @param keys This is 2.385 * @param item The item to compare the key with.386 *387 * @return true on match388 * @return false on no match389 *390 */391 bool irq_lin_compare(sysarg_t key[], size_t keys, link_t *item)392 {393 irq_t *irq = list_get_instance(item, irq_t, link);394 irq_ht_mode_t mode = (irq_ht_mode_t) key[IRQ_HT_KEY_MODE];395 bool rv;396 397 irq_spinlock_lock(&irq->lock, false);398 if (mode == IRQ_HT_MODE_CLAIM) {399 /* Invoked by irq_dispatch_and_lock() */400 rv = (irq->claim(irq) == IRQ_ACCEPT);401 } else {402 /* Invoked by irq_find_and_lock() */403 rv = false;404 }405 406 /* unlock only on non-match */407 if (!rv)408 irq_spinlock_unlock(&irq->lock, false);409 410 return rv;411 }412 413 /** Unlock IRQ structure after hash_table_remove().414 *415 * @param lnk Link in the removed and locked IRQ structure.416 *417 */418 void irq_lin_remove(link_t *lnk)419 {420 irq_t *irq __attribute__((unused))421 = hash_table_get_instance(lnk, irq_t, link);422 irq_spinlock_unlock(&irq->lock, false);423 }424 425 284 /** @} 426 285 */
Note:
See TracChangeset
for help on using the changeset viewer.