aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2015-11-11 14:45:30 -0500
committerLinus Walleij <linus.walleij@linaro.org>2015-12-13 11:36:02 -0500
commit10cf4899f8affa468b9140f377857bfe3f563012 (patch)
tree4330bab7ac37927291d85871798e7b18d4271ac7
parent8005c49d9aea74d382f474ce11afbbc7d7130bec (diff)
gpiolib: tighten up ACPI legacy gpio lookups
We should not fall back to the legacy unnamed gpio lookup style if the driver requests gpios with different names, because we'll give out the same gpio twice. Let's keep track of the names that were used for the device and only do the fallback for the first name used. Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/gpio/gpiolib-acpi.c43
-rw-r--r--drivers/gpio/gpiolib.c3
-rw-r--r--drivers/gpio/gpiolib.h8
3 files changed, 54 insertions, 0 deletions
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 16a7b6816744..7ab7bc3c9300 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -922,3 +922,46 @@ int acpi_gpio_count(struct device *dev, const char *con_id)
922 } 922 }
923 return count; 923 return count;
924} 924}
925
926struct acpi_crs_lookup {
927 struct list_head node;
928 struct acpi_device *adev;
929 const char *con_id;
930};
931
932static DEFINE_MUTEX(acpi_crs_lookup_lock);
933static LIST_HEAD(acpi_crs_lookup_list);
934
935bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id)
936{
937 struct acpi_crs_lookup *l, *lookup = NULL;
938
939 /* Never allow fallback if the device has properties */
940 if (adev->data.properties || adev->driver_gpios)
941 return false;
942
943 mutex_lock(&acpi_crs_lookup_lock);
944
945 list_for_each_entry(l, &acpi_crs_lookup_list, node) {
946 if (l->adev == adev) {
947 lookup = l;
948 break;
949 }
950 }
951
952 if (!lookup) {
953 lookup = kmalloc(sizeof(*lookup), GFP_KERNEL);
954 if (lookup) {
955 lookup->adev = adev;
956 lookup->con_id = con_id;
957 list_add_tail(&lookup->node, &acpi_crs_lookup_list);
958 }
959 }
960
961 mutex_unlock(&acpi_crs_lookup_lock);
962
963 return lookup &&
964 ((!lookup->con_id && !con_id) ||
965 (lookup->con_id && con_id &&
966 strcmp(lookup->con_id, con_id) == 0));
967}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index a18f00fc1bb8..3ca6c9f4391e 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1868,6 +1868,9 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
1868 1868
1869 /* Then from plain _CRS GPIOs */ 1869 /* Then from plain _CRS GPIOs */
1870 if (IS_ERR(desc)) { 1870 if (IS_ERR(desc)) {
1871 if (!acpi_can_fallback_to_crs(adev, con_id))
1872 return ERR_PTR(-ENOENT);
1873
1871 desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info); 1874 desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info);
1872 if (IS_ERR(desc)) 1875 if (IS_ERR(desc))
1873 return desc; 1876 return desc;
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 98ab08c0aa2d..2b87cbd68478 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -47,6 +47,8 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
47 struct acpi_gpio_info *info); 47 struct acpi_gpio_info *info);
48 48
49int acpi_gpio_count(struct device *dev, const char *con_id); 49int acpi_gpio_count(struct device *dev, const char *con_id);
50
51bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id);
50#else 52#else
51static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } 53static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
52static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { } 54static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
@@ -73,6 +75,12 @@ static inline int acpi_gpio_count(struct device *dev, const char *con_id)
73{ 75{
74 return -ENODEV; 76 return -ENODEV;
75} 77}
78
79static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev,
80 const char *con_id)
81{
82 return false;
83}
76#endif 84#endif
77 85
78struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, 86struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,