19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2016 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifndef __ISR_H
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define __ISR_H
1921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
20c42a1e1071937ae48b7aa5d6291a32c29078b74bAdrian Roos#include <stdbool.h>
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdint.h>
2257ceaaa0aa1fece02ff82cd903a26bdf65131c56Christopher Tate
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cpu.h>
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <list.h>
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <util.h>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <seos.h>
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct ChainedInterrupt {
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    link_t isrs;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void (*const enable)(struct ChainedInterrupt *);
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void (*const disable)(struct ChainedInterrupt *);
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
34182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct ChainedIsr {
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    link_t node;
374870e9d5eba59fb257a87f97f1adf0b734cf48d3Dianne Hackborn
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t maxLatencyNs;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4080a4af2bbc6af42ae605e454bf89558e564f5244Dianne Hackborn    bool (*func)(struct ChainedIsr *);
41c4a07d1caa9befd4fa8165ff05fa5e92480d8e27Christopher Tate    uint16_t tid;
42c42a1e1071937ae48b7aa5d6291a32c29078b74bAdrian Roos};
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
44c42a1e1071937ae48b7aa5d6291a32c29078b74bAdrian Roosstatic inline void chainIsr(struct ChainedInterrupt *interrupt, struct ChainedIsr *isr)
453d658bf20e2d56e36941e7407deebeec1276fbcfDianne Hackborn{
46c42a1e1071937ae48b7aa5d6291a32c29078b74bAdrian Roos    interrupt->disable(interrupt);
478a9b22056b13477f59df934928c00c58b5871c95Joe Onorato    isr->tid = osGetCurrentTid();
483d658bf20e2d56e36941e7407deebeec1276fbcfDianne Hackborn    list_add_tail(&interrupt->isrs, &isr->node);
49c42a1e1071937ae48b7aa5d6291a32c29078b74bAdrian Roos    interrupt->enable(interrupt);
50043fcd9847a804bc6394728e5785aecc495e6347Dianne Hackborn}
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
524cb338de350d7afa8c2113a76d45c417c695be66Christopher Tatestatic inline void unchainIsr(struct ChainedInterrupt *interrupt, struct ChainedIsr *isr)
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    interrupt->disable(interrupt);
55043fcd9847a804bc6394728e5785aecc495e6347Dianne Hackborn    isr->tid = 0;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    list_delete(&isr->node);
578103890a59de6ed4abaedaad80e66666ea59f9b5Dianne Hackborn    if (!list_is_empty(&interrupt->isrs))
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        interrupt->enable(interrupt);
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
611f7b4134db07acbb429cd770441ff460fa6f4b1bMike Lockwoodstatic inline bool dispatchIsr(struct ChainedInterrupt *interrupt)
621590f1ee7b7b7962f08e8cc29b9891b2ad124c9bChristopher Tate{
6318a75f1123e7bb9c68d983ab266c1ad886b347a5Christopher Tate    struct link_t *cur, *tmp;
64c42a1e1071937ae48b7aa5d6291a32c29078b74bAdrian Roos    bool handled = false;
654870e9d5eba59fb257a87f97f1adf0b734cf48d3Dianne Hackborn    uint16_t oldTid = osGetCurrentTid();
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    list_iterate(&interrupt->isrs, cur, tmp) {
68e0a22b324d0e3157e570ea5f71cc682fa9696e01Christopher Tate        struct ChainedIsr *curIsr = container_of(cur, struct ChainedIsr, node);
69e0a22b324d0e3157e570ea5f71cc682fa9696e01Christopher Tate        osSetCurrentTid(curIsr->tid);
70e0a22b324d0e3157e570ea5f71cc682fa9696e01Christopher Tate        handled = curIsr->func(curIsr);
71e0a22b324d0e3157e570ea5f71cc682fa9696e01Christopher Tate        if (handled)
72e0a22b324d0e3157e570ea5f71cc682fa9696e01Christopher Tate            break;
738103890a59de6ed4abaedaad80e66666ea59f9b5Dianne Hackborn    }
748103890a59de6ed4abaedaad80e66666ea59f9b5Dianne Hackborn    osSetCurrentTid(oldTid);
75182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return handled;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
79e0a22b324d0e3157e570ea5f71cc682fa9696e01Christopher Tatestatic inline int unchainIsrAll(struct ChainedInterrupt *interrupt, uint32_t tid)
80498c6cbd78f42d4f6d2568ead6c2697fcfaa326eChristopher Tate{
81498c6cbd78f42d4f6d2568ead6c2697fcfaa326eChristopher Tate    int count = 0;
82498c6cbd78f42d4f6d2568ead6c2697fcfaa326eChristopher Tate    struct link_t *cur, *tmp;
83498c6cbd78f42d4f6d2568ead6c2697fcfaa326eChristopher Tate
84498c6cbd78f42d4f6d2568ead6c2697fcfaa326eChristopher Tate    list_iterate(&interrupt->isrs, cur, tmp) {
85498c6cbd78f42d4f6d2568ead6c2697fcfaa326eChristopher Tate        struct ChainedIsr *curIsr = container_of(cur, struct ChainedIsr, node);
86e0a22b324d0e3157e570ea5f71cc682fa9696e01Christopher Tate        if (curIsr->tid == tid) {
87e0a22b324d0e3157e570ea5f71cc682fa9696e01Christopher Tate            unchainIsr(interrupt, curIsr);
88182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski            count++;
89e0a22b324d0e3157e570ea5f71cc682fa9696e01Christopher Tate        }
90182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski    }
91182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski
92b8849c1e858c726eaf04f7c5a5a08036faa171dfChristopher Tate    return count;
93e0a22b324d0e3157e570ea5f71cc682fa9696e01Christopher Tate}
94182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski
95182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinskistatic inline uint32_t maxLatencyIsr(struct ChainedInterrupt *interrupt)
96182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski{
97182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski    struct link_t *cur, *tmp;
98182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski    uint32_t latency = 0;
99182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski
100182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski    list_iterate(&interrupt->isrs, cur, tmp) {
101c42a1e1071937ae48b7aa5d6291a32c29078b74bAdrian Roos        struct ChainedIsr *curIsr = container_of(cur, struct ChainedIsr, node);
1021e38382b542f5cef9957a89692b02c55a3dd351cDianne Hackborn        if (!latency || (curIsr->maxLatencyNs && curIsr->maxLatencyNs < latency))
103182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski            latency = curIsr->maxLatencyNs;
104182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski    }
105c42a1e1071937ae48b7aa5d6291a32c29078b74bAdrian Roos
106182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski    return latency;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
108182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif /* __ISR_H */
110182f73fc4da13a6417e5086ec9ecce80eb8423caAdam Lesinski