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