Rev 4055 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4055 | Rev 4296 | ||
|---|---|---|---|
| Line 126... | Line 126... | ||
| 126 | return code; |
126 | return code; |
| 127 | } |
127 | } |
| 128 | 128 | ||
| 129 | /** Register an answerbox as a receiving end for IRQ notifications. |
129 | /** Register an answerbox as a receiving end for IRQ notifications. |
| 130 | * |
130 | * |
| 131 | * @param box Receiving answerbox. |
131 | * @param box Receiving answerbox. |
| 132 | * @param inr IRQ number. |
132 | * @param inr IRQ number. |
| 133 | * @param devno Device number. |
133 | * @param devno Device number. |
| 134 | * @param method Method to be associated with the notification. |
134 | * @param method Method to be associated with the notification. |
| 135 | * @param ucode Uspace pointer to top-half pseudocode. |
135 | * @param ucode Uspace pointer to top-half pseudocode. |
| - | 136 | * |
|
| - | 137 | * @return EBADMEM, ENOENT or EEXISTS on failure or 0 on success. |
|
| 136 | * |
138 | * |
| 137 | * @return EBADMEM, ENOENT or EEXISTS on failure or 0 on success. |
- | |
| 138 | */ |
139 | */ |
| 139 | int ipc_irq_register(answerbox_t *box, inr_t inr, devno_t devno, |
140 | int ipc_irq_register(answerbox_t *box, inr_t inr, devno_t devno, |
| 140 | unative_t method, irq_code_t *ucode) |
141 | unative_t method, irq_code_t *ucode) |
| 141 | { |
142 | { |
| 142 | ipl_t ipl; |
143 | ipl_t ipl; |
| 143 | irq_code_t *code; |
144 | irq_code_t *code; |
| 144 | irq_t *irq; |
145 | irq_t *irq; |
| - | 146 | link_t *hlp; |
|
| 145 | unative_t key[] = { |
147 | unative_t key[] = { |
| 146 | (unative_t) inr, |
148 | (unative_t) inr, |
| 147 | (unative_t) devno |
149 | (unative_t) devno |
| 148 | }; |
150 | }; |
| 149 | 151 | ||
| 150 | if (ucode) { |
152 | if (ucode) { |
| 151 | code = code_from_uspace(ucode); |
153 | code = code_from_uspace(ucode); |
| 152 | if (!code) |
154 | if (!code) |
| 153 | return EBADMEM; |
155 | return EBADMEM; |
| 154 | } else { |
156 | } else { |
| 155 | code = NULL; |
157 | code = NULL; |
| 156 | } |
158 | } |
| 157 | 159 | ||
| 158 | /* |
160 | /* |
| 159 | * Allocate and populate the IRQ structure. |
161 | * Allocate and populate the IRQ structure. |
| 160 | */ |
162 | */ |
| 161 | irq = malloc(sizeof(irq_t), 0); |
163 | irq = malloc(sizeof(irq_t), 0); |
| 162 | irq_initialize(irq); |
164 | irq_initialize(irq); |
| Line 167... | Line 169... | ||
| 167 | irq->notif_cfg.notify = true; |
169 | irq->notif_cfg.notify = true; |
| 168 | irq->notif_cfg.answerbox = box; |
170 | irq->notif_cfg.answerbox = box; |
| 169 | irq->notif_cfg.method = method; |
171 | irq->notif_cfg.method = method; |
| 170 | irq->notif_cfg.code = code; |
172 | irq->notif_cfg.code = code; |
| 171 | irq->notif_cfg.counter = 0; |
173 | irq->notif_cfg.counter = 0; |
| 172 | 174 | ||
| 173 | /* |
175 | /* |
| 174 | * Enlist the IRQ structure in the uspace IRQ hash table and the |
176 | * Enlist the IRQ structure in the uspace IRQ hash table and the |
| 175 | * answerbox's list. |
177 | * answerbox's list. |
| 176 | */ |
178 | */ |
| 177 | ipl = interrupts_disable(); |
179 | ipl = interrupts_disable(); |
| 178 | spinlock_lock(&irq_uspace_hash_table_lock); |
180 | spinlock_lock(&irq_uspace_hash_table_lock); |
| 179 | spinlock_lock(&irq->lock); |
181 | hlp = hash_table_find(&irq_uspace_hash_table, key); |
| - | 182 | if (hlp) { |
|
| 180 | spinlock_lock(&box->irq_lock); |
183 | irq_t *hirq __attribute__((unused)) |
| 181 | if (hash_table_find(&irq_uspace_hash_table, key)) { |
184 | = hash_table_get_instance(hlp, irq_t, link); |
| - | 185 | ||
| - | 186 | /* hirq is locked */ |
|
| - | 187 | spinlock_unlock(&hirq->lock); |
|
| 182 | code_free(code); |
188 | code_free(code); |
| 183 | spinlock_unlock(&box->irq_lock); |
- | |
| 184 | spinlock_unlock(&irq->lock); |
- | |
| 185 | spinlock_unlock(&irq_uspace_hash_table_lock); |
189 | spinlock_unlock(&irq_uspace_hash_table_lock); |
| 186 | free(irq); |
190 | free(irq); |
| 187 | interrupts_restore(ipl); |
191 | interrupts_restore(ipl); |
| 188 | return EEXISTS; |
192 | return EEXISTS; |
| 189 | } |
193 | } |
| - | 194 | ||
| - | 195 | spinlock_lock(&irq->lock); /* Not really necessary, but paranoid */ |
|
| - | 196 | spinlock_lock(&box->irq_lock); |
|
| 190 | hash_table_insert(&irq_uspace_hash_table, key, &irq->link); |
197 | hash_table_insert(&irq_uspace_hash_table, key, &irq->link); |
| 191 | list_append(&irq->notif_cfg.link, &box->irq_head); |
198 | list_append(&irq->notif_cfg.link, &box->irq_head); |
| 192 | spinlock_unlock(&box->irq_lock); |
199 | spinlock_unlock(&box->irq_lock); |
| 193 | spinlock_unlock(&irq->lock); |
200 | spinlock_unlock(&irq->lock); |
| 194 | spinlock_unlock(&irq_uspace_hash_table_lock); |
201 | spinlock_unlock(&irq_uspace_hash_table_lock); |
| 195 | 202 | ||
| 196 | interrupts_restore(ipl); |
203 | interrupts_restore(ipl); |
| 197 | return EOK; |
204 | return EOK; |
| 198 | } |
205 | } |
| 199 | 206 | ||
| 200 | /** Unregister task from IRQ notification. |
207 | /** Unregister task from IRQ notification. |
| Line 220... | Line 227... | ||
| 220 | spinlock_unlock(&irq_uspace_hash_table_lock); |
227 | spinlock_unlock(&irq_uspace_hash_table_lock); |
| 221 | interrupts_restore(ipl); |
228 | interrupts_restore(ipl); |
| 222 | return ENOENT; |
229 | return ENOENT; |
| 223 | } |
230 | } |
| 224 | irq = hash_table_get_instance(lnk, irq_t, link); |
231 | irq = hash_table_get_instance(lnk, irq_t, link); |
| 225 | spinlock_lock(&irq->lock); |
232 | /* irq is locked */ |
| 226 | spinlock_lock(&box->irq_lock); |
233 | spinlock_lock(&box->irq_lock); |
| 227 | 234 | ||
| 228 | ASSERT(irq->notif_cfg.answerbox == box); |
235 | ASSERT(irq->notif_cfg.answerbox == box); |
| 229 | 236 | ||
| 230 | /* Free up the pseudo code and associated structures. */ |
237 | /* Free up the pseudo code and associated structures. */ |
| 231 | code_free(irq->notif_cfg.code); |
238 | code_free(irq->notif_cfg.code); |
| 232 | 239 | ||
| 233 | /* Remove the IRQ from the answerbox's list. */ |
240 | /* Remove the IRQ from the answerbox's list. */ |
| 234 | list_remove(&irq->notif_cfg.link); |
241 | list_remove(&irq->notif_cfg.link); |
| 235 | 242 | ||
| - | 243 | /* |
|
| - | 244 | * We need to drop the IRQ lock now because hash_table_remove() will try |
|
| - | 245 | * to reacquire it. That basically violates the natural locking order, |
|
| - | 246 | * but a deadlock in hash_table_remove() is prevented by the fact that |
|
| - | 247 | * we already held the IRQ lock and didn't drop the hash table lock in |
|
| - | 248 | * the meantime. |
|
| - | 249 | */ |
|
| - | 250 | spinlock_unlock(&irq->lock); |
|
| - | 251 | ||
| 236 | /* Remove the IRQ from the uspace IRQ hash table. */ |
252 | /* Remove the IRQ from the uspace IRQ hash table. */ |
| 237 | hash_table_remove(&irq_uspace_hash_table, key, 2); |
253 | hash_table_remove(&irq_uspace_hash_table, key, 2); |
| 238 | 254 | ||
| 239 | spinlock_unlock(&irq_uspace_hash_table_lock); |
255 | spinlock_unlock(&irq_uspace_hash_table_lock); |
| 240 | spinlock_unlock(&irq->lock); |
- | |
| 241 | spinlock_unlock(&box->irq_lock); |
256 | spinlock_unlock(&box->irq_lock); |
| 242 | 257 | ||
| 243 | /* Free up the IRQ structure. */ |
258 | /* Free up the IRQ structure. */ |
| 244 | free(irq); |
259 | free(irq); |
| 245 | 260 | ||
| Line 289... | Line 304... | ||
| 289 | ASSERT(irq->notif_cfg.answerbox == box); |
304 | ASSERT(irq->notif_cfg.answerbox == box); |
| 290 | 305 | ||
| 291 | /* Unlist from the answerbox. */ |
306 | /* Unlist from the answerbox. */ |
| 292 | list_remove(&irq->notif_cfg.link); |
307 | list_remove(&irq->notif_cfg.link); |
| 293 | 308 | ||
| 294 | /* Remove from the hash table. */ |
- | |
| 295 | hash_table_remove(&irq_uspace_hash_table, key, 2); |
- | |
| 296 | - | ||
| 297 | /* Free up the pseudo code and associated structures. */ |
309 | /* Free up the pseudo code and associated structures. */ |
| 298 | code_free(irq->notif_cfg.code); |
310 | code_free(irq->notif_cfg.code); |
| 299 | 311 | ||
| - | 312 | /* |
|
| - | 313 | * We need to drop the IRQ lock now because hash_table_remove() |
|
| - | 314 | * will try to reacquire it. That basically violates the natural |
|
| - | 315 | * locking order, but a deadlock in hash_table_remove() is |
|
| - | 316 | * prevented by the fact that we already held the IRQ lock and |
|
| - | 317 | * didn't drop the hash table lock in the meantime. |
|
| - | 318 | */ |
|
| 300 | spinlock_unlock(&irq->lock); |
319 | spinlock_unlock(&irq->lock); |
| - | 320 | ||
| - | 321 | /* Remove from the hash table. */ |
|
| - | 322 | hash_table_remove(&irq_uspace_hash_table, key, 2); |
|
| - | 323 | ||
| 301 | free(irq); |
324 | free(irq); |
| 302 | } |
325 | } |
| 303 | 326 | ||
| 304 | spinlock_unlock(&box->irq_lock); |
327 | spinlock_unlock(&box->irq_lock); |
| 305 | spinlock_unlock(&irq_uspace_hash_table_lock); |
328 | spinlock_unlock(&irq_uspace_hash_table_lock); |