Merge remote-tracking branches 'spi/topic/devprop', 'spi/topic/fsl', 'spi/topic/fsl...
[sfrench/cifs-2.6.git] / drivers / spi / spi.c
index f274df9e0e3e2265c723139bb2b2f92ad72e32ba..2c36c0ac708ab7d4e2b7d2123fbf00136bec6e5a 100644 (file)
 #include <linux/of_gpio.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_domain.h>
 #include <linux/of_gpio.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_domain.h>
+#include <linux/property.h>
 #include <linux/export.h>
 #include <linux/sched/rt.h>
 #include <linux/export.h>
 #include <linux/sched/rt.h>
+#include <uapi/linux/sched/types.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/ioport.h>
@@ -599,13 +601,28 @@ struct spi_device *spi_new_device(struct spi_master *master,
        proxy->controller_data = chip->controller_data;
        proxy->controller_state = NULL;
 
        proxy->controller_data = chip->controller_data;
        proxy->controller_state = NULL;
 
-       status = spi_add_device(proxy);
-       if (status < 0) {
-               spi_dev_put(proxy);
-               return NULL;
+       if (chip->properties) {
+               status = device_add_properties(&proxy->dev, chip->properties);
+               if (status) {
+                       dev_err(&master->dev,
+                               "failed to add properties to '%s': %d\n",
+                               chip->modalias, status);
+                       goto err_dev_put;
+               }
        }
 
        }
 
+       status = spi_add_device(proxy);
+       if (status < 0)
+               goto err_remove_props;
+
        return proxy;
        return proxy;
+
+err_remove_props:
+       if (chip->properties)
+               device_remove_properties(&proxy->dev);
+err_dev_put:
+       spi_dev_put(proxy);
+       return NULL;
 }
 EXPORT_SYMBOL_GPL(spi_new_device);
 
 }
 EXPORT_SYMBOL_GPL(spi_new_device);
 
@@ -663,6 +680,7 @@ static void spi_match_master_to_boardinfo(struct spi_master *master,
  *
  * The board info passed can safely be __initdata ... but be careful of
  * any embedded pointers (platform_data, etc), they're copied as-is.
  *
  * The board info passed can safely be __initdata ... but be careful of
  * any embedded pointers (platform_data, etc), they're copied as-is.
+ * Device properties are deep-copied though.
  *
  * Return: zero on success, else a negative error code.
  */
  *
  * Return: zero on success, else a negative error code.
  */
@@ -672,7 +690,7 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n)
        int i;
 
        if (!n)
        int i;
 
        if (!n)
-               return -EINVAL;
+               return 0;
 
        bi = kcalloc(n, sizeof(*bi), GFP_KERNEL);
        if (!bi)
 
        bi = kcalloc(n, sizeof(*bi), GFP_KERNEL);
        if (!bi)
@@ -682,6 +700,13 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n)
                struct spi_master *master;
 
                memcpy(&bi->board_info, info, sizeof(*info));
                struct spi_master *master;
 
                memcpy(&bi->board_info, info, sizeof(*info));
+               if (info->properties) {
+                       bi->board_info.properties =
+                                       property_entries_dup(info->properties);
+                       if (IS_ERR(bi->board_info.properties))
+                               return PTR_ERR(bi->board_info.properties);
+               }
+
                mutex_lock(&board_lock);
                list_add_tail(&bi->list, &board_list);
                list_for_each_entry(master, &spi_master_list, list)
                mutex_lock(&board_lock);
                list_add_tail(&bi->list, &board_list);
                list_for_each_entry(master, &spi_master_list, list)
@@ -1014,7 +1039,7 @@ static int spi_transfer_one_message(struct spi_master *master,
                                ret = 0;
                                ms = 8LL * 1000LL * xfer->len;
                                do_div(ms, xfer->speed_hz);
                                ret = 0;
                                ms = 8LL * 1000LL * xfer->len;
                                do_div(ms, xfer->speed_hz);
-                               ms += ms + 100; /* some tolerance */
+                               ms += ms + 200; /* some tolerance */
 
                                if (ms > UINT_MAX)
                                        ms = UINT_MAX;
 
                                if (ms > UINT_MAX)
                                        ms = UINT_MAX;
@@ -1738,13 +1763,15 @@ static acpi_status acpi_register_spi_device(struct spi_master *master,
                return AE_OK;
        }
 
                return AE_OK;
        }
 
+       acpi_set_modalias(adev, acpi_device_hid(adev), spi->modalias,
+                         sizeof(spi->modalias));
+
        if (spi->irq < 0)
                spi->irq = acpi_dev_gpio_irq_get(adev, 0);
 
        acpi_device_set_enumerated(adev);
 
        adev->power.flags.ignore_parent = true;
        if (spi->irq < 0)
                spi->irq = acpi_dev_gpio_irq_get(adev, 0);
 
        acpi_device_set_enumerated(adev);
 
        adev->power.flags.ignore_parent = true;
-       strlcpy(spi->modalias, acpi_device_hid(adev), sizeof(spi->modalias));
        if (spi_add_device(spi)) {
                adev->power.flags.ignore_parent = false;
                dev_err(&master->dev, "failed to add SPI device %s from ACPI\n",
        if (spi_add_device(spi)) {
                adev->power.flags.ignore_parent = false;
                dev_err(&master->dev, "failed to add SPI device %s from ACPI\n",