Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
[linux-2.6] / arch / mips / include / asm / smtc_ipi.h
1 /*
2  * Definitions used in MIPS MT SMTC "Interprocessor Interrupt" code.
3  */
4 #ifndef __ASM_SMTC_IPI_H
5 #define __ASM_SMTC_IPI_H
6
7 #include <linux/spinlock.h>
8
9 //#define SMTC_IPI_DEBUG
10
11 #ifdef SMTC_IPI_DEBUG
12 #include <asm/mipsregs.h>
13 #include <asm/mipsmtregs.h>
14 #endif /* SMTC_IPI_DEBUG */
15
16 /*
17  * An IPI "message"
18  */
19
20 struct smtc_ipi {
21         struct smtc_ipi *flink;
22         int type;
23         void *arg;
24         int dest;
25 #ifdef  SMTC_IPI_DEBUG
26         int sender;
27         long stamp;
28 #endif /* SMTC_IPI_DEBUG */
29 };
30
31 /*
32  * Defined IPI Types
33  */
34
35 #define LINUX_SMP_IPI 1
36 #define SMTC_CLOCK_TICK 2
37 #define IRQ_AFFINITY_IPI 3
38
39 /*
40  * A queue of IPI messages
41  */
42
43 struct smtc_ipi_q {
44         struct smtc_ipi *head;
45         spinlock_t lock;
46         struct smtc_ipi *tail;
47         int depth;
48 };
49
50 static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
51 {
52         unsigned long flags;
53
54         spin_lock_irqsave(&q->lock, flags);
55         if (q->head == NULL)
56                 q->head = q->tail = p;
57         else
58                 q->tail->flink = p;
59         p->flink = NULL;
60         q->tail = p;
61         q->depth++;
62 #ifdef  SMTC_IPI_DEBUG
63         p->sender = read_c0_tcbind();
64         p->stamp = read_c0_count();
65 #endif /* SMTC_IPI_DEBUG */
66         spin_unlock_irqrestore(&q->lock, flags);
67 }
68
69 static inline struct smtc_ipi *__smtc_ipi_dq(struct smtc_ipi_q *q)
70 {
71         struct smtc_ipi *p;
72
73         if (q->head == NULL)
74                 p = NULL;
75         else {
76                 p = q->head;
77                 q->head = q->head->flink;
78                 q->depth--;
79                 /* Arguably unnecessary, but leaves queue cleaner */
80                 if (q->head == NULL)
81                         q->tail = NULL;
82         }
83
84         return p;
85 }
86
87 static inline struct smtc_ipi *smtc_ipi_dq(struct smtc_ipi_q *q)
88 {
89         unsigned long flags;
90         struct smtc_ipi *p;
91
92         spin_lock_irqsave(&q->lock, flags);
93         p = __smtc_ipi_dq(q);
94         spin_unlock_irqrestore(&q->lock, flags);
95
96         return p;
97 }
98
99 static inline void smtc_ipi_req(struct smtc_ipi_q *q, struct smtc_ipi *p)
100 {
101         unsigned long flags;
102
103         spin_lock_irqsave(&q->lock, flags);
104         if (q->head == NULL) {
105                 q->head = q->tail = p;
106                 p->flink = NULL;
107         } else {
108                 p->flink = q->head;
109                 q->head = p;
110         }
111         q->depth++;
112         spin_unlock_irqrestore(&q->lock, flags);
113 }
114
115 static inline int smtc_ipi_qdepth(struct smtc_ipi_q *q)
116 {
117         unsigned long flags;
118         int retval;
119
120         spin_lock_irqsave(&q->lock, flags);
121         retval = q->depth;
122         spin_unlock_irqrestore(&q->lock, flags);
123         return retval;
124 }
125
126 extern void smtc_send_ipi(int cpu, int type, unsigned int action);
127
128 #endif /* __ASM_SMTC_IPI_H */