]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - drivers/rapidio/rio-access.c
video: tegra: host: fix integer overflows
[linux-2.6.git] / drivers / rapidio / rio-access.c
1 /*
2  * RapidIO configuration space access support
3  *
4  * Copyright 2005 MontaVista Software, Inc.
5  * Matt Porter <mporter@kernel.crashing.org>
6  *
7  * This program is free software; you can redistribute  it and/or modify it
8  * under  the terms of  the GNU General  Public License as published by the
9  * Free Software Foundation;  either version 2 of the  License, or (at your
10  * option) any later version.
11  */
12
13 #include <linux/rio.h>
14 #include <linux/module.h>
15
16 /*
17  * These interrupt-safe spinlocks protect all accesses to RIO
18  * configuration space and doorbell access.
19  */
20 static DEFINE_SPINLOCK(rio_config_lock);
21 static DEFINE_SPINLOCK(rio_doorbell_lock);
22
23 /*
24  *  Wrappers for all RIO configuration access functions.  They just check
25  *  alignment, do locking and call the low-level functions pointed to
26  *  by rio_mport->ops.
27  */
28
29 #define RIO_8_BAD 0
30 #define RIO_16_BAD (offset & 1)
31 #define RIO_32_BAD (offset & 3)
32
33 /**
34  * RIO_LOP_READ - Generate rio_local_read_config_* functions
35  * @size: Size of configuration space read (8, 16, 32 bits)
36  * @type: C type of value argument
37  * @len: Length of configuration space read (1, 2, 4 bytes)
38  *
39  * Generates rio_local_read_config_* functions used to access
40  * configuration space registers on the local device.
41  */
42 #define RIO_LOP_READ(size,type,len) \
43 int __rio_local_read_config_##size \
44         (struct rio_mport *mport, u32 offset, type *value)              \
45 {                                                                       \
46         int res;                                                        \
47         unsigned long flags;                                            \
48         u32 data = 0;                                                   \
49         if (RIO_##size##_BAD) return RIO_BAD_SIZE;                      \
50         spin_lock_irqsave(&rio_config_lock, flags);                     \
51         res = mport->ops->lcread(mport, mport->id, offset, len, &data); \
52         *value = (type)data;                                            \
53         spin_unlock_irqrestore(&rio_config_lock, flags);                \
54         return res;                                                     \
55 }
56
57 /**
58  * RIO_LOP_WRITE - Generate rio_local_write_config_* functions
59  * @size: Size of configuration space write (8, 16, 32 bits)
60  * @type: C type of value argument
61  * @len: Length of configuration space write (1, 2, 4 bytes)
62  *
63  * Generates rio_local_write_config_* functions used to access
64  * configuration space registers on the local device.
65  */
66 #define RIO_LOP_WRITE(size,type,len) \
67 int __rio_local_write_config_##size \
68         (struct rio_mport *mport, u32 offset, type value)               \
69 {                                                                       \
70         int res;                                                        \
71         unsigned long flags;                                            \
72         if (RIO_##size##_BAD) return RIO_BAD_SIZE;                      \
73         spin_lock_irqsave(&rio_config_lock, flags);                     \
74         res = mport->ops->lcwrite(mport, mport->id, offset, len, value);\
75         spin_unlock_irqrestore(&rio_config_lock, flags);                \
76         return res;                                                     \
77 }
78
79 RIO_LOP_READ(8, u8, 1)
80 RIO_LOP_READ(16, u16, 2)
81 RIO_LOP_READ(32, u32, 4)
82 RIO_LOP_WRITE(8, u8, 1)
83 RIO_LOP_WRITE(16, u16, 2)
84 RIO_LOP_WRITE(32, u32, 4)
85
86 EXPORT_SYMBOL_GPL(__rio_local_read_config_8);
87 EXPORT_SYMBOL_GPL(__rio_local_read_config_16);
88 EXPORT_SYMBOL_GPL(__rio_local_read_config_32);
89 EXPORT_SYMBOL_GPL(__rio_local_write_config_8);
90 EXPORT_SYMBOL_GPL(__rio_local_write_config_16);
91 EXPORT_SYMBOL_GPL(__rio_local_write_config_32);
92
93 /**
94  * RIO_OP_READ - Generate rio_mport_read_config_* functions
95  * @size: Size of configuration space read (8, 16, 32 bits)
96  * @type: C type of value argument
97  * @len: Length of configuration space read (1, 2, 4 bytes)
98  *
99  * Generates rio_mport_read_config_* functions used to access
100  * configuration space registers on the local device.
101  */
102 #define RIO_OP_READ(size,type,len) \
103 int rio_mport_read_config_##size \
104         (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value)     \
105 {                                                                       \
106         int res;                                                        \
107         unsigned long flags;                                            \
108         u32 data = 0;                                                   \
109         if (RIO_##size##_BAD) return RIO_BAD_SIZE;                      \
110         spin_lock_irqsave(&rio_config_lock, flags);                     \
111         res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \
112         *value = (type)data;                                            \
113         spin_unlock_irqrestore(&rio_config_lock, flags);                \
114         return res;                                                     \
115 }
116
117 /**
118  * RIO_OP_WRITE - Generate rio_mport_write_config_* functions
119  * @size: Size of configuration space write (8, 16, 32 bits)
120  * @type: C type of value argument
121  * @len: Length of configuration space write (1, 2, 4 bytes)
122  *
123  * Generates rio_mport_write_config_* functions used to access
124  * configuration space registers on the local device.
125  */
126 #define RIO_OP_WRITE(size,type,len) \
127 int rio_mport_write_config_##size \
128         (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value)      \
129 {                                                                       \
130         int res;                                                        \
131         unsigned long flags;                                            \
132         if (RIO_##size##_BAD) return RIO_BAD_SIZE;                      \
133         spin_lock_irqsave(&rio_config_lock, flags);                     \
134         res = mport->ops->cwrite(mport, mport->id, destid, hopcount, offset, len, value); \
135         spin_unlock_irqrestore(&rio_config_lock, flags);                \
136         return res;                                                     \
137 }
138
139 RIO_OP_READ(8, u8, 1)
140 RIO_OP_READ(16, u16, 2)
141 RIO_OP_READ(32, u32, 4)
142 RIO_OP_WRITE(8, u8, 1)
143 RIO_OP_WRITE(16, u16, 2)
144 RIO_OP_WRITE(32, u32, 4)
145
146 EXPORT_SYMBOL_GPL(rio_mport_read_config_8);
147 EXPORT_SYMBOL_GPL(rio_mport_read_config_16);
148 EXPORT_SYMBOL_GPL(rio_mport_read_config_32);
149 EXPORT_SYMBOL_GPL(rio_mport_write_config_8);
150 EXPORT_SYMBOL_GPL(rio_mport_write_config_16);
151 EXPORT_SYMBOL_GPL(rio_mport_write_config_32);
152
153 /**
154  * rio_mport_send_doorbell - Send a doorbell message
155  *
156  * @mport: RIO master port
157  * @destid: RIO device destination ID
158  * @data: Doorbell message data
159  *
160  * Send a doorbell message to a RIO device. The doorbell message
161  * has a 16-bit info field provided by the data argument.
162  */
163 int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data)
164 {
165         int res;
166         unsigned long flags;
167
168         spin_lock_irqsave(&rio_doorbell_lock, flags);
169         res = mport->ops->dsend(mport, mport->id, destid, data);
170         spin_unlock_irqrestore(&rio_doorbell_lock, flags);
171
172         return res;
173 }
174
175 EXPORT_SYMBOL_GPL(rio_mport_send_doorbell);