aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi.c
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2006-01-08 16:34:25 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-13 19:29:55 -0500
commit0c868461fcb8413cb9f691d68e5b99b0fd3c0737 (patch)
treeb43db6239f5d72a279b35b14de85cf34d8f6bc74 /drivers/spi/spi.c
parentb885244eb2628e0b8206e7edaaa6a314da78e9a4 (diff)
[PATCH] SPI core tweaks, bugfix
This includes various updates to the SPI core: - Fixes a driver model refcount bug in spi_unregister_master() paths. - The spi_master structures now have wrappers which help keep drivers from needing class-level get/put for device data or for refcounts. - Check for a few setup errors that would cause oopsing later. - Docs say more about memory management. Highlights the use of DMA-safe i/o buffers, and zero-initializing spi_message and such metadata. - Provide a simple alloc/free for spi_message and its spi_transfer; this is only one of the possible memory management policies. Nothing to break code that already works. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r--drivers/spi/spi.c45
1 files changed, 28 insertions, 17 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 2ecb86cb3689..3ecedccdb96c 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -38,7 +38,7 @@ static void spidev_release(struct device *dev)
38 if (spi->master->cleanup) 38 if (spi->master->cleanup)
39 spi->master->cleanup(spi); 39 spi->master->cleanup(spi);
40 40
41 class_device_put(&spi->master->cdev); 41 spi_master_put(spi->master);
42 kfree(dev); 42 kfree(dev);
43} 43}
44 44
@@ -90,7 +90,7 @@ static int spi_suspend(struct device *dev, pm_message_t message)
90 int value; 90 int value;
91 struct spi_driver *drv = to_spi_driver(dev->driver); 91 struct spi_driver *drv = to_spi_driver(dev->driver);
92 92
93 if (!drv || !drv->suspend) 93 if (!drv->suspend)
94 return 0; 94 return 0;
95 95
96 /* suspend will stop irqs and dma; no more i/o */ 96 /* suspend will stop irqs and dma; no more i/o */
@@ -105,7 +105,7 @@ static int spi_resume(struct device *dev)
105 int value; 105 int value;
106 struct spi_driver *drv = to_spi_driver(dev->driver); 106 struct spi_driver *drv = to_spi_driver(dev->driver);
107 107
108 if (!drv || !drv->resume) 108 if (!drv->resume)
109 return 0; 109 return 0;
110 110
111 /* resume may restart the i/o queue */ 111 /* resume may restart the i/o queue */
@@ -198,7 +198,7 @@ spi_new_device(struct spi_master *master, struct spi_board_info *chip)
198 198
199 /* NOTE: caller did any chip->bus_num checks necessary */ 199 /* NOTE: caller did any chip->bus_num checks necessary */
200 200
201 if (!class_device_get(&master->cdev)) 201 if (!spi_master_get(master))
202 return NULL; 202 return NULL;
203 203
204 proxy = kzalloc(sizeof *proxy, GFP_KERNEL); 204 proxy = kzalloc(sizeof *proxy, GFP_KERNEL);
@@ -244,7 +244,7 @@ spi_new_device(struct spi_master *master, struct spi_board_info *chip)
244 return proxy; 244 return proxy;
245 245
246fail: 246fail:
247 class_device_put(&master->cdev); 247 spi_master_put(master);
248 kfree(proxy); 248 kfree(proxy);
249 return NULL; 249 return NULL;
250} 250}
@@ -324,8 +324,6 @@ static void spi_master_release(struct class_device *cdev)
324 struct spi_master *master; 324 struct spi_master *master;
325 325
326 master = container_of(cdev, struct spi_master, cdev); 326 master = container_of(cdev, struct spi_master, cdev);
327 put_device(master->cdev.dev);
328 master->cdev.dev = NULL;
329 kfree(master); 327 kfree(master);
330} 328}
331 329
@@ -339,8 +337,9 @@ static struct class spi_master_class = {
339/** 337/**
340 * spi_alloc_master - allocate SPI master controller 338 * spi_alloc_master - allocate SPI master controller
341 * @dev: the controller, possibly using the platform_bus 339 * @dev: the controller, possibly using the platform_bus
342 * @size: how much driver-private data to preallocate; a pointer to this 340 * @size: how much driver-private data to preallocate; the pointer to this
343 * memory in the class_data field of the returned class_device 341 * memory is in the class_data field of the returned class_device,
342 * accessible with spi_master_get_devdata().
344 * 343 *
345 * This call is used only by SPI master controller drivers, which are the 344 * This call is used only by SPI master controller drivers, which are the
346 * only ones directly touching chip registers. It's how they allocate 345 * only ones directly touching chip registers. It's how they allocate
@@ -350,14 +349,17 @@ static struct class spi_master_class = {
350 * master structure on success, else NULL. 349 * master structure on success, else NULL.
351 * 350 *
352 * The caller is responsible for assigning the bus number and initializing 351 * The caller is responsible for assigning the bus number and initializing
353 * the master's methods before calling spi_add_master(), or else (on error) 352 * the master's methods before calling spi_add_master(); and (after errors
354 * calling class_device_put() to prevent a memory leak. 353 * adding the device) calling spi_master_put() to prevent a memory leak.
355 */ 354 */
356struct spi_master * __init_or_module 355struct spi_master * __init_or_module
357spi_alloc_master(struct device *dev, unsigned size) 356spi_alloc_master(struct device *dev, unsigned size)
358{ 357{
359 struct spi_master *master; 358 struct spi_master *master;
360 359
360 if (!dev)
361 return NULL;
362
361 master = kzalloc(size + sizeof *master, SLAB_KERNEL); 363 master = kzalloc(size + sizeof *master, SLAB_KERNEL);
362 if (!master) 364 if (!master)
363 return NULL; 365 return NULL;
@@ -365,7 +367,7 @@ spi_alloc_master(struct device *dev, unsigned size)
365 class_device_initialize(&master->cdev); 367 class_device_initialize(&master->cdev);
366 master->cdev.class = &spi_master_class; 368 master->cdev.class = &spi_master_class;
367 master->cdev.dev = get_device(dev); 369 master->cdev.dev = get_device(dev);
368 class_set_devdata(&master->cdev, &master[1]); 370 spi_master_set_devdata(master, &master[1]);
369 371
370 return master; 372 return master;
371} 373}
@@ -387,6 +389,8 @@ EXPORT_SYMBOL_GPL(spi_alloc_master);
387 * 389 *
388 * This must be called from context that can sleep. It returns zero on 390 * This must be called from context that can sleep. It returns zero on
389 * success, else a negative error code (dropping the master's refcount). 391 * success, else a negative error code (dropping the master's refcount).
392 * After a successful return, the caller is responsible for calling
393 * spi_unregister_master().
390 */ 394 */
391int __init_or_module 395int __init_or_module
392spi_register_master(struct spi_master *master) 396spi_register_master(struct spi_master *master)
@@ -396,6 +400,9 @@ spi_register_master(struct spi_master *master)
396 int status = -ENODEV; 400 int status = -ENODEV;
397 int dynamic = 0; 401 int dynamic = 0;
398 402
403 if (!dev)
404 return -ENODEV;
405
399 /* convention: dynamically assigned bus IDs count down from the max */ 406 /* convention: dynamically assigned bus IDs count down from the max */
400 if (master->bus_num == 0) { 407 if (master->bus_num == 0) {
401 master->bus_num = atomic_dec_return(&dyn_bus_id); 408 master->bus_num = atomic_dec_return(&dyn_bus_id);
@@ -425,7 +432,7 @@ EXPORT_SYMBOL_GPL(spi_register_master);
425static int __unregister(struct device *dev, void *unused) 432static int __unregister(struct device *dev, void *unused)
426{ 433{
427 /* note: before about 2.6.14-rc1 this would corrupt memory: */ 434 /* note: before about 2.6.14-rc1 this would corrupt memory: */
428 device_unregister(dev); 435 spi_unregister_device(to_spi_device(dev));
429 return 0; 436 return 0;
430} 437}
431 438
@@ -440,8 +447,9 @@ static int __unregister(struct device *dev, void *unused)
440 */ 447 */
441void spi_unregister_master(struct spi_master *master) 448void spi_unregister_master(struct spi_master *master)
442{ 449{
443 class_device_unregister(&master->cdev);
444 (void) device_for_each_child(master->cdev.dev, NULL, __unregister); 450 (void) device_for_each_child(master->cdev.dev, NULL, __unregister);
451 class_device_unregister(&master->cdev);
452 master->cdev.dev = NULL;
445} 453}
446EXPORT_SYMBOL_GPL(spi_unregister_master); 454EXPORT_SYMBOL_GPL(spi_unregister_master);
447 455
@@ -487,6 +495,9 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master);
487 * by leaving it selected in anticipation that the next message will go 495 * by leaving it selected in anticipation that the next message will go
488 * to the same chip. (That may increase power usage.) 496 * to the same chip. (That may increase power usage.)
489 * 497 *
498 * Also, the caller is guaranteeing that the memory associated with the
499 * message will not be freed before this call returns.
500 *
490 * The return value is a negative error code if the message could not be 501 * The return value is a negative error code if the message could not be
491 * submitted, else zero. When the value is zero, then message->status is 502 * submitted, else zero. When the value is zero, then message->status is
492 * also defined: it's the completion code for the transfer, either zero 503 * also defined: it's the completion code for the transfer, either zero
@@ -524,9 +535,9 @@ static u8 *buf;
524 * is zero for success, else a negative errno status code. 535 * is zero for success, else a negative errno status code.
525 * This call may only be used from a context that may sleep. 536 * This call may only be used from a context that may sleep.
526 * 537 *
527 * Parameters to this routine are always copied using a small buffer, 538 * Parameters to this routine are always copied using a small buffer;
528 * large transfers should use use spi_{async,sync}() calls with 539 * performance-sensitive or bulk transfer code should instead use
529 * dma-safe buffers. 540 * spi_{async,sync}() calls with dma-safe buffers.
530 */ 541 */
531int spi_write_then_read(struct spi_device *spi, 542int spi_write_then_read(struct spi_device *spi,
532 const u8 *txbuf, unsigned n_tx, 543 const u8 *txbuf, unsigned n_tx,