]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/spi/spi.c
slc90e66: fix deadlock on error handling
[linux-2.6-omap-h63xx.git] / drivers / spi / spi.c
index 018884d7a5fac3e8c69d2cb0b062e3d79a865de8..89769ce16f882058934698ce566b804aa3a13e2d 100644 (file)
@@ -67,14 +67,11 @@ static int spi_match_device(struct device *dev, struct device_driver *drv)
        return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0;
 }
 
-static int spi_uevent(struct device *dev, char **envp, int num_envp,
-               char *buffer, int buffer_size)
+static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        const struct spi_device         *spi = to_spi_device(dev);
 
-       envp[0] = buffer;
-       snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias);
-       envp[1] = NULL;
+       add_uevent_var(env, "MODALIAS=%s", spi->modalias);
        return 0;
 }
 
@@ -200,15 +197,30 @@ static DEFINE_MUTEX(board_lock);
  * platforms may not be able to use spi_register_board_info though, and
  * this is exported so that for example a USB or parport based adapter
  * driver could add devices (which it would learn about out-of-band).
+ *
+ * Returns the new device, or NULL.
  */
 struct spi_device *spi_new_device(struct spi_master *master,
                                  struct spi_board_info *chip)
 {
        struct spi_device       *proxy;
-       struct device           *dev = master->cdev.dev;
+       struct device           *dev = master->dev.parent;
        int                     status;
 
-       /* NOTE:  caller did any chip->bus_num checks necessary */
+       /* NOTE:  caller did any chip->bus_num checks necessary.
+        *
+        * Also, unless we change the return value convention to use
+        * error-or-pointer (not NULL-or-pointer), troubleshootability
+        * suggests syslogged diagnostics are best here (ugh).
+        */
+
+       /* Chipselects are numbered 0..max; validate. */
+       if (chip->chip_select >= master->num_chipselect) {
+               dev_err(dev, "cs%d > max %d\n",
+                       chip->chip_select,
+                       master->num_chipselect);
+               return NULL;
+       }
 
        if (!spi_master_get(master))
                return NULL;
@@ -227,7 +239,7 @@ struct spi_device *spi_new_device(struct spi_master *master,
        proxy->modalias = chip->modalias;
 
        snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
-                       "%s.%u", master->cdev.class_id,
+                       "%s.%u", master->dev.bus_id,
                        chip->chip_select);
        proxy->dev.parent = dev;
        proxy->dev.bus = &spi_bus_type;
@@ -236,10 +248,10 @@ struct spi_device *spi_new_device(struct spi_master *master,
        proxy->controller_state = NULL;
        proxy->dev.release = spidev_release;
 
-       /* drivers may modify this default i/o setup */
+       /* drivers may modify this initial i/o setup */
        status = master->setup(proxy);
        if (status < 0) {
-               dev_dbg(dev, "can't %s %s, status %d\n",
+               dev_err(dev, "can't %s %s, status %d\n",
                                "setup", proxy->dev.bus_id, status);
                goto fail;
        }
@@ -249,7 +261,7 @@ struct spi_device *spi_new_device(struct spi_master *master,
         */
        status = device_register(&proxy->dev);
        if (status < 0) {
-               dev_dbg(dev, "can't %s %s, status %d\n",
+               dev_err(dev, "can't %s %s, status %d\n",
                                "add", proxy->dev.bus_id, status);
                goto fail;
        }
@@ -303,11 +315,9 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
  * creates board info from kernel command lines
  */
 
-static void __init_or_module
-scan_boardinfo(struct spi_master *master)
+static void scan_boardinfo(struct spi_master *master)
 {
        struct boardinfo        *bi;
-       struct device           *dev = master->cdev.dev;
 
        mutex_lock(&board_lock);
        list_for_each_entry(bi, &board_list, list) {
@@ -317,17 +327,9 @@ scan_boardinfo(struct spi_master *master)
                for (n = bi->n_board_info; n > 0; n--, chip++) {
                        if (chip->bus_num != master->bus_num)
                                continue;
-                       /* some controllers only have one chip, so they
-                        * might not use chipselects.  otherwise, the
-                        * chipselects are numbered 0..max.
+                       /* NOTE: this relies on spi_new_device to
+                        * issue diagnostics when given bogus inputs
                         */
-                       if (chip->chip_select >= master->num_chipselect
-                                       && master->num_chipselect) {
-                               dev_dbg(dev, "cs%d > max %d\n",
-                                       chip->chip_select,
-                                       master->num_chipselect);
-                               continue;
-                       }
                        (void) spi_new_device(master, chip);
                }
        }
@@ -336,18 +338,18 @@ scan_boardinfo(struct spi_master *master)
 
 /*-------------------------------------------------------------------------*/
 
-static void spi_master_release(struct class_device *cdev)
+static void spi_master_release(struct device *dev)
 {
        struct spi_master *master;
 
-       master = container_of(cdev, struct spi_master, cdev);
+       master = container_of(dev, struct spi_master, dev);
        kfree(master);
 }
 
 static struct class spi_master_class = {
        .name           = "spi_master",
        .owner          = THIS_MODULE,
-       .release        = spi_master_release,
+       .dev_release    = spi_master_release,
 };
 
 
@@ -355,7 +357,7 @@ static struct class spi_master_class = {
  * spi_alloc_master - allocate SPI master controller
  * @dev: the controller, possibly using the platform_bus
  * @size: how much zeroed driver-private data to allocate; the pointer to this
- *     memory is in the class_data field of the returned class_device,
+ *     memory is in the driver_data field of the returned device,
  *     accessible with spi_master_get_devdata().
  * Context: can sleep
  *
@@ -381,9 +383,9 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
        if (!master)
                return NULL;
 
-       class_device_initialize(&master->cdev);
-       master->cdev.class = &spi_master_class;
-       master->cdev.dev = get_device(dev);
+       device_initialize(&master->dev);
+       master->dev.class = &spi_master_class;
+       master->dev.parent = get_device(dev);
        spi_master_set_devdata(master, &master[1]);
 
        return master;
@@ -413,15 +415,24 @@ EXPORT_SYMBOL_GPL(spi_alloc_master);
 int spi_register_master(struct spi_master *master)
 {
        static atomic_t         dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
-       struct device           *dev = master->cdev.dev;
+       struct device           *dev = master->dev.parent;
        int                     status = -ENODEV;
        int                     dynamic = 0;
 
        if (!dev)
                return -ENODEV;
 
+       /* even if it's just one always-selected device, there must
+        * be at least one chipselect
+        */
+       if (master->num_chipselect == 0)
+               return -EINVAL;
+
        /* convention:  dynamically assigned bus IDs count down from the max */
        if (master->bus_num < 0) {
+               /* FIXME switch to an IDR based scheme, something like
+                * I2C now uses, so we can't run out of "dynamic" IDs
+                */
                master->bus_num = atomic_dec_return(&dyn_bus_id);
                dynamic = 1;
        }
@@ -429,12 +440,12 @@ int spi_register_master(struct spi_master *master)
        /* register the device, then userspace will see it.
         * registration fails if the bus ID is in use.
         */
-       snprintf(master->cdev.class_id, sizeof master->cdev.class_id,
+       snprintf(master->dev.bus_id, sizeof master->dev.bus_id,
                "spi%u", master->bus_num);
-       status = class_device_add(&master->cdev);
+       status = device_add(&master->dev);
        if (status < 0)
                goto done;
-       dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id,
+       dev_dbg(dev, "registered master %s%s\n", master->dev.bus_id,
                        dynamic ? " (dynamic)" : "");
 
        /* populate children from any spi device tables */
@@ -467,8 +478,8 @@ void spi_unregister_master(struct spi_master *master)
 {
        int dummy;
 
-       dummy = device_for_each_child(master->cdev.dev, NULL, __unregister);
-       class_device_unregister(&master->cdev);
+       dummy = device_for_each_child(master->dev.parent, NULL, __unregister);
+       device_unregister(&master->dev);
 }
 EXPORT_SYMBOL_GPL(spi_unregister_master);
 
@@ -484,13 +495,13 @@ EXPORT_SYMBOL_GPL(spi_unregister_master);
  */
 struct spi_master *spi_busnum_to_master(u16 bus_num)
 {
-       struct class_device     *cdev;
+       struct device           *dev;
        struct spi_master       *master = NULL;
        struct spi_master       *m;
 
        down(&spi_master_class.sem);
-       list_for_each_entry(cdev, &spi_master_class.children, node) {
-               m = container_of(cdev, struct spi_master, cdev);
+       list_for_each_entry(dev, &spi_master_class.children, node) {
+               m = container_of(dev, struct spi_master, dev);
                if (m->bus_num == bus_num) {
                        master = spi_master_get(m);
                        break;