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 int resched_flag; /* reschedule already queued */
49 };
50
smtc_ipi_nq(struct smtc_ipi_q * q,struct smtc_ipi * p)51 static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
52 {
53 unsigned long flags;
54
55 spin_lock_irqsave(&q->lock, flags);
56 if (q->head == NULL)
57 q->head = q->tail = p;
58 else
59 q->tail->flink = p;
60 p->flink = NULL;
61 q->tail = p;
62 q->depth++;
63 #ifdef SMTC_IPI_DEBUG
64 p->sender = read_c0_tcbind();
65 p->stamp = read_c0_count();
66 #endif /* SMTC_IPI_DEBUG */
67 spin_unlock_irqrestore(&q->lock, flags);
68 }
69
__smtc_ipi_dq(struct smtc_ipi_q * q)70 static inline struct smtc_ipi *__smtc_ipi_dq(struct smtc_ipi_q *q)
71 {
72 struct smtc_ipi *p;
73
74 if (q->head == NULL)
75 p = NULL;
76 else {
77 p = q->head;
78 q->head = q->head->flink;
79 q->depth--;
80 /* Arguably unnecessary, but leaves queue cleaner */
81 if (q->head == NULL)
82 q->tail = NULL;
83 }
84
85 return p;
86 }
87
smtc_ipi_dq(struct smtc_ipi_q * q)88 static inline struct smtc_ipi *smtc_ipi_dq(struct smtc_ipi_q *q)
89 {
90 unsigned long flags;
91 struct smtc_ipi *p;
92
93 spin_lock_irqsave(&q->lock, flags);
94 p = __smtc_ipi_dq(q);
95 spin_unlock_irqrestore(&q->lock, flags);
96
97 return p;
98 }
99
smtc_ipi_req(struct smtc_ipi_q * q,struct smtc_ipi * p)100 static inline void smtc_ipi_req(struct smtc_ipi_q *q, struct smtc_ipi *p)
101 {
102 unsigned long flags;
103
104 spin_lock_irqsave(&q->lock, flags);
105 if (q->head == NULL) {
106 q->head = q->tail = p;
107 p->flink = NULL;
108 } else {
109 p->flink = q->head;
110 q->head = p;
111 }
112 q->depth++;
113 spin_unlock_irqrestore(&q->lock, flags);
114 }
115
smtc_ipi_qdepth(struct smtc_ipi_q * q)116 static inline int smtc_ipi_qdepth(struct smtc_ipi_q *q)
117 {
118 unsigned long flags;
119 int retval;
120
121 spin_lock_irqsave(&q->lock, flags);
122 retval = q->depth;
123 spin_unlock_irqrestore(&q->lock, flags);
124 return retval;
125 }
126
127 extern void smtc_send_ipi(int cpu, int type, unsigned int action);
128
129 #endif /* __ASM_SMTC_IPI_H */
130