remove mips gcc4 inline patch - fixed upstream
[openwrt.git] / target / linux / generic / patches-2.6.35 / 910-backport-spi-bus-locking-api.patch
1 From cf32b71e981ca63e8f349d8585ca2a3583b556e0 Mon Sep 17 00:00:00 2001
2 From: Ernst Schwab <eschwab@online.de>
3 Date: Mon, 28 Jun 2010 17:49:29 -0700
4 Subject: [PATCH] spi/mmc_spi: SPI bus locking API, using mutex
5
6 SPI bus locking API to allow exclusive access to the SPI bus, especially, but
7 not limited to, for the mmc_spi driver.
8
9 Coded according to an outline from Grant Likely; here is his
10 specification (accidentally swapped function names corrected):
11
12 It requires 3 things to be added to struct spi_master.
13 - 1 Mutex
14 - 1 spin lock
15 - 1 flag.
16
17 The mutex protects spi_sync, and provides sleeping "for free"
18 The spinlock protects the atomic spi_async call.
19 The flag is set when the lock is obtained, and checked while holding
20 the spinlock in spi_async(). If the flag is checked, then spi_async()
21 must fail immediately.
22
23 The current runtime API looks like this:
24 spi_async(struct spi_device*, struct spi_message*);
25 spi_sync(struct spi_device*, struct spi_message*);
26
27 The API needs to be extended to this:
28 spi_async(struct spi_device*, struct spi_message*)
29 spi_sync(struct spi_device*, struct spi_message*)
30 spi_bus_lock(struct spi_master*) /* although struct spi_device* might
31 be easier */
32 spi_bus_unlock(struct spi_master*)
33 spi_async_locked(struct spi_device*, struct spi_message*)
34 spi_sync_locked(struct spi_device*, struct spi_message*)
35
36 Drivers can only call the last two if they already hold the spi_master_lock().
37
38 spi_bus_lock() obtains the mutex, obtains the spin lock, sets the
39 flag, and releases the spin lock before returning. It doesn't even
40 need to sleep while waiting for "in-flight" spi_transactions to
41 complete because its purpose is to guarantee no additional
42 transactions are added. It does not guarantee that the bus is idle.
43
44 spi_bus_unlock() clears the flag and releases the mutex, which will
45 wake up any waiters.
46
47 The difference between spi_async() and spi_async_locked() is that the
48 locked version bypasses the check of the lock flag. Both versions
49 need to obtain the spinlock.
50
51 The difference between spi_sync() and spi_sync_locked() is that
52 spi_sync() must hold the mutex while enqueuing a new transfer.
53 spi_sync_locked() doesn't because the mutex is already held. Note
54 however that spi_sync must *not* continue to hold the mutex while
55 waiting for the transfer to complete, otherwise only one transfer
56 could be queued up at a time!
57
58 Almost no code needs to be written. The current spi_async() and
59 spi_sync() can probably be renamed to __spi_async() and __spi_sync()
60 so that spi_async(), spi_sync(), spi_async_locked() and
61 spi_sync_locked() can just become wrappers around the common code.
62
63 spi_sync() is protected by a mutex because it can sleep
64 spi_async() needs to be protected with a flag and a spinlock because
65 it can be called atomically and must not sleep
66
67 Signed-off-by: Ernst Schwab <eschwab@online.de>
68 [grant.likely@secretlab.ca: use spin_lock_irqsave()]
69 Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
70 Tested-by: Matt Fleming <matt@console-pimps.org>
71 Tested-by: Antonio Ospite <ospite@studenti.unina.it>
72 ---
73 drivers/spi/spi.c | 225 ++++++++++++++++++++++++++++++++++++++++-------
74 include/linux/spi/spi.h | 12 +++
75 2 files changed, 204 insertions(+), 33 deletions(-)
76
77 --- a/drivers/spi/spi.c
78 +++ b/drivers/spi/spi.c
79 @@ -527,6 +527,10 @@ int spi_register_master(struct spi_maste
80 dynamic = 1;
81 }
82
83 + spin_lock_init(&master->bus_lock_spinlock);
84 + mutex_init(&master->bus_lock_mutex);
85 + master->bus_lock_flag = 0;
86 +
87 /* register the device, then userspace will see it.
88 * registration fails if the bus ID is in use.
89 */
90 @@ -666,6 +670,35 @@ int spi_setup(struct spi_device *spi)
91 }
92 EXPORT_SYMBOL_GPL(spi_setup);
93
94 +static int __spi_async(struct spi_device *spi, struct spi_message *message)
95 +{
96 + struct spi_master *master = spi->master;
97 +
98 + /* Half-duplex links include original MicroWire, and ones with
99 + * only one data pin like SPI_3WIRE (switches direction) or where
100 + * either MOSI or MISO is missing. They can also be caused by
101 + * software limitations.
102 + */
103 + if ((master->flags & SPI_MASTER_HALF_DUPLEX)
104 + || (spi->mode & SPI_3WIRE)) {
105 + struct spi_transfer *xfer;
106 + unsigned flags = master->flags;
107 +
108 + list_for_each_entry(xfer, &message->transfers, transfer_list) {
109 + if (xfer->rx_buf && xfer->tx_buf)
110 + return -EINVAL;
111 + if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf)
112 + return -EINVAL;
113 + if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf)
114 + return -EINVAL;
115 + }
116 + }
117 +
118 + message->spi = spi;
119 + message->status = -EINPROGRESS;
120 + return master->transfer(spi, message);
121 +}
122 +
123 /**
124 * spi_async - asynchronous SPI transfer
125 * @spi: device with which data will be exchanged
126 @@ -698,33 +731,68 @@ EXPORT_SYMBOL_GPL(spi_setup);
127 int spi_async(struct spi_device *spi, struct spi_message *message)
128 {
129 struct spi_master *master = spi->master;
130 + int ret;
131 + unsigned long flags;
132
133 - /* Half-duplex links include original MicroWire, and ones with
134 - * only one data pin like SPI_3WIRE (switches direction) or where
135 - * either MOSI or MISO is missing. They can also be caused by
136 - * software limitations.
137 - */
138 - if ((master->flags & SPI_MASTER_HALF_DUPLEX)
139 - || (spi->mode & SPI_3WIRE)) {
140 - struct spi_transfer *xfer;
141 - unsigned flags = master->flags;
142 + spin_lock_irqsave(&master->bus_lock_spinlock, flags);
143
144 - list_for_each_entry(xfer, &message->transfers, transfer_list) {
145 - if (xfer->rx_buf && xfer->tx_buf)
146 - return -EINVAL;
147 - if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf)
148 - return -EINVAL;
149 - if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf)
150 - return -EINVAL;
151 - }
152 - }
153 + if (master->bus_lock_flag)
154 + ret = -EBUSY;
155 + else
156 + ret = __spi_async(spi, message);
157
158 - message->spi = spi;
159 - message->status = -EINPROGRESS;
160 - return master->transfer(spi, message);
161 + spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
162 +
163 + return ret;
164 }
165 EXPORT_SYMBOL_GPL(spi_async);
166
167 +/**
168 + * spi_async_locked - version of spi_async with exclusive bus usage
169 + * @spi: device with which data will be exchanged
170 + * @message: describes the data transfers, including completion callback
171 + * Context: any (irqs may be blocked, etc)
172 + *
173 + * This call may be used in_irq and other contexts which can't sleep,
174 + * as well as from task contexts which can sleep.
175 + *
176 + * The completion callback is invoked in a context which can't sleep.
177 + * Before that invocation, the value of message->status is undefined.
178 + * When the callback is issued, message->status holds either zero (to
179 + * indicate complete success) or a negative error code. After that
180 + * callback returns, the driver which issued the transfer request may
181 + * deallocate the associated memory; it's no longer in use by any SPI
182 + * core or controller driver code.
183 + *
184 + * Note that although all messages to a spi_device are handled in
185 + * FIFO order, messages may go to different devices in other orders.
186 + * Some device might be higher priority, or have various "hard" access
187 + * time requirements, for example.
188 + *
189 + * On detection of any fault during the transfer, processing of
190 + * the entire message is aborted, and the device is deselected.
191 + * Until returning from the associated message completion callback,
192 + * no other spi_message queued to that device will be processed.
193 + * (This rule applies equally to all the synchronous transfer calls,
194 + * which are wrappers around this core asynchronous primitive.)
195 + */
196 +int spi_async_locked(struct spi_device *spi, struct spi_message *message)
197 +{
198 + struct spi_master *master = spi->master;
199 + int ret;
200 + unsigned long flags;
201 +
202 + spin_lock_irqsave(&master->bus_lock_spinlock, flags);
203 +
204 + ret = __spi_async(spi, message);
205 +
206 + spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
207 +
208 + return ret;
209 +
210 +}
211 +EXPORT_SYMBOL_GPL(spi_async_locked);
212 +
213
214 /*-------------------------------------------------------------------------*/
215
216 @@ -738,6 +806,32 @@ static void spi_complete(void *arg)
217 complete(arg);
218 }
219
220 +static int __spi_sync(struct spi_device *spi, struct spi_message *message,
221 + int bus_locked)
222 +{
223 + DECLARE_COMPLETION_ONSTACK(done);
224 + int status;
225 + struct spi_master *master = spi->master;
226 +
227 + message->complete = spi_complete;
228 + message->context = &done;
229 +
230 + if (!bus_locked)
231 + mutex_lock(&master->bus_lock_mutex);
232 +
233 + status = spi_async_locked(spi, message);
234 +
235 + if (!bus_locked)
236 + mutex_unlock(&master->bus_lock_mutex);
237 +
238 + if (status == 0) {
239 + wait_for_completion(&done);
240 + status = message->status;
241 + }
242 + message->context = NULL;
243 + return status;
244 +}
245 +
246 /**
247 * spi_sync - blocking/synchronous SPI data transfers
248 * @spi: device with which data will be exchanged
249 @@ -761,21 +855,86 @@ static void spi_complete(void *arg)
250 */
251 int spi_sync(struct spi_device *spi, struct spi_message *message)
252 {
253 - DECLARE_COMPLETION_ONSTACK(done);
254 - int status;
255 -
256 - message->complete = spi_complete;
257 - message->context = &done;
258 - status = spi_async(spi, message);
259 - if (status == 0) {
260 - wait_for_completion(&done);
261 - status = message->status;
262 - }
263 - message->context = NULL;
264 - return status;
265 + return __spi_sync(spi, message, 0);
266 }
267 EXPORT_SYMBOL_GPL(spi_sync);
268
269 +/**
270 + * spi_sync_locked - version of spi_sync with exclusive bus usage
271 + * @spi: device with which data will be exchanged
272 + * @message: describes the data transfers
273 + * Context: can sleep
274 + *
275 + * This call may only be used from a context that may sleep. The sleep
276 + * is non-interruptible, and has no timeout. Low-overhead controller
277 + * drivers may DMA directly into and out of the message buffers.
278 + *
279 + * This call should be used by drivers that require exclusive access to the
280 + * SPI bus. It has to be preceeded by a spi_bus_lock call. The SPI bus must
281 + * be released by a spi_bus_unlock call when the exclusive access is over.
282 + *
283 + * It returns zero on success, else a negative error code.
284 + */
285 +int spi_sync_locked(struct spi_device *spi, struct spi_message *message)
286 +{
287 + return __spi_sync(spi, message, 1);
288 +}
289 +EXPORT_SYMBOL_GPL(spi_sync_locked);
290 +
291 +/**
292 + * spi_bus_lock - obtain a lock for exclusive SPI bus usage
293 + * @master: SPI bus master that should be locked for exclusive bus access
294 + * Context: can sleep
295 + *
296 + * This call may only be used from a context that may sleep. The sleep
297 + * is non-interruptible, and has no timeout.
298 + *
299 + * This call should be used by drivers that require exclusive access to the
300 + * SPI bus. The SPI bus must be released by a spi_bus_unlock call when the
301 + * exclusive access is over. Data transfer must be done by spi_sync_locked
302 + * and spi_async_locked calls when the SPI bus lock is held.
303 + *
304 + * It returns zero on success, else a negative error code.
305 + */
306 +int spi_bus_lock(struct spi_master *master)
307 +{
308 + unsigned long flags;
309 +
310 + mutex_lock(&master->bus_lock_mutex);
311 +
312 + spin_lock_irqsave(&master->bus_lock_spinlock, flags);
313 + master->bus_lock_flag = 1;
314 + spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
315 +
316 + /* mutex remains locked until spi_bus_unlock is called */
317 +
318 + return 0;
319 +}
320 +EXPORT_SYMBOL_GPL(spi_bus_lock);
321 +
322 +/**
323 + * spi_bus_unlock - release the lock for exclusive SPI bus usage
324 + * @master: SPI bus master that was locked for exclusive bus access
325 + * Context: can sleep
326 + *
327 + * This call may only be used from a context that may sleep. The sleep
328 + * is non-interruptible, and has no timeout.
329 + *
330 + * This call releases an SPI bus lock previously obtained by an spi_bus_lock
331 + * call.
332 + *
333 + * It returns zero on success, else a negative error code.
334 + */
335 +int spi_bus_unlock(struct spi_master *master)
336 +{
337 + master->bus_lock_flag = 0;
338 +
339 + mutex_unlock(&master->bus_lock_mutex);
340 +
341 + return 0;
342 +}
343 +EXPORT_SYMBOL_GPL(spi_bus_unlock);
344 +
345 /* portable code must never pass more than 32 bytes */
346 #define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
347
348 --- a/include/linux/spi/spi.h
349 +++ b/include/linux/spi/spi.h
350 @@ -262,6 +262,13 @@ struct spi_master {
351 #define SPI_MASTER_NO_RX BIT(1) /* can't do buffer read */
352 #define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */
353
354 + /* lock and mutex for SPI bus locking */
355 + spinlock_t bus_lock_spinlock;
356 + struct mutex bus_lock_mutex;
357 +
358 + /* flag indicating that the SPI bus is locked for exclusive use */
359 + bool bus_lock_flag;
360 +
361 /* Setup mode and clock, etc (spi driver may call many times).
362 *
363 * IMPORTANT: this may be called when transfers to another
364 @@ -542,6 +549,8 @@ static inline void spi_message_free(stru
365
366 extern int spi_setup(struct spi_device *spi);
367 extern int spi_async(struct spi_device *spi, struct spi_message *message);
368 +extern int spi_async_locked(struct spi_device *spi,
369 + struct spi_message *message);
370
371 /*---------------------------------------------------------------------------*/
372
373 @@ -551,6 +560,9 @@ extern int spi_async(struct spi_device *
374 */
375
376 extern int spi_sync(struct spi_device *spi, struct spi_message *message);
377 +extern int spi_sync_locked(struct spi_device *spi, struct spi_message *message);
378 +extern int spi_bus_lock(struct spi_master *master);
379 +extern int spi_bus_unlock(struct spi_master *master);
380
381 /**
382 * spi_write - SPI synchronous write
This page took 0.066236 seconds and 5 git commands to generate.