From 830ae442202e314c2bdf7cb4c7cc64d76db0e197 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 31 May 2016 17:32:30 +0900 Subject: extcon: Remove the deprecated extcon functions This patch removes the deprecated extcon functions using string type to identify the type of external connector. The Commit 2a9de9c0f08d61 ("extcon: Use the unique id for external connector instead of string) uses the unique id to separate the type of external connector instead of string name. - extcon_register_interest() - extcon_unregister_interest() - extcon_set_cable_state() - extcon_get_cable_state() And, extcon_register_interest() finds the first extcon device to include the requested external connector from extcon client device and then register the notifier if extcon device argument is NULL. Instead, extcon_register_notifier() supports this feature. But, this patch remains the deprecatd function definition to prevent the build break. Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon.c | 201 ++++++------------------------------------------ 1 file changed, 24 insertions(+), 177 deletions(-) (limited to 'drivers/extcon/extcon.c') diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 21a123cadf78..4fef9ab4b148 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -127,38 +127,6 @@ static int find_cable_index_by_id(struct extcon_dev *edev, const unsigned int id return -EINVAL; } -static int find_cable_id_by_name(struct extcon_dev *edev, const char *name) -{ - int id = -EINVAL; - int i = 0; - - /* Find the id of extcon cable */ - while (extcon_name[i]) { - if (!strncmp(extcon_name[i], name, CABLE_NAME_MAX)) { - id = i; - break; - } - i++; - } - - return id; -} - -static int find_cable_index_by_name(struct extcon_dev *edev, const char *name) -{ - int id; - - if (edev->max_supported == 0) - return -EINVAL; - - /* Find the the number of extcon cable */ - id = find_cable_id_by_name(edev, name); - if (id < 0) - return id; - - return find_cable_index_by_id(edev, id); -} - static bool is_extcon_changed(u32 prev, u32 new, int idx, bool *attached) { if (((prev >> idx) & 0x1) != ((new >> idx) & 0x1)) { @@ -373,25 +341,6 @@ int extcon_get_cable_state_(struct extcon_dev *edev, const unsigned int id) } EXPORT_SYMBOL_GPL(extcon_get_cable_state_); -/** - * extcon_get_cable_state() - Get the status of a specific cable. - * @edev: the extcon device that has the cable. - * @cable_name: cable name. - * - * Note that this is slower than extcon_get_cable_state_. - */ -int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name) -{ - int id; - - id = find_cable_id_by_name(edev, cable_name); - if (id < 0) - return id; - - return extcon_get_cable_state_(edev, id); -} -EXPORT_SYMBOL_GPL(extcon_get_cable_state); - /** * extcon_set_cable_state_() - Set the status of a specific cable. * @edev: the extcon device that has the cable. @@ -421,28 +370,6 @@ int extcon_set_cable_state_(struct extcon_dev *edev, unsigned int id, } EXPORT_SYMBOL_GPL(extcon_set_cable_state_); -/** - * extcon_set_cable_state() - Set the status of a specific cable. - * @edev: the extcon device that has the cable. - * @cable_name: cable name. - * @cable_state: the new cable status. The default semantics is - * true: attached / false: detached. - * - * Note that this is slower than extcon_set_cable_state_. - */ -int extcon_set_cable_state(struct extcon_dev *edev, - const char *cable_name, bool cable_state) -{ - int id; - - id = find_cable_id_by_name(edev, cable_name); - if (id < 0) - return id; - - return extcon_set_cable_state_(edev, id, cable_state); -} -EXPORT_SYMBOL_GPL(extcon_set_cable_state); - /** * extcon_get_extcon_dev() - Get the extcon device instance from the name * @extcon_name: The extcon name provided with extcon_dev_register() @@ -466,105 +393,6 @@ out: } EXPORT_SYMBOL_GPL(extcon_get_extcon_dev); -/** - * extcon_register_interest() - Register a notifier for a state change of a - * specific cable, not an entier set of cables of a - * extcon device. - * @obj: an empty extcon_specific_cable_nb object to be returned. - * @extcon_name: the name of extcon device. - * if NULL, extcon_register_interest will register - * every cable with the target cable_name given. - * @cable_name: the target cable name. - * @nb: the notifier block to get notified. - * - * Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets - * the struct for you. - * - * extcon_register_interest is a helper function for those who want to get - * notification for a single specific cable's status change. If a user wants - * to get notification for any changes of all cables of a extcon device, - * he/she should use the general extcon_register_notifier(). - * - * Note that the second parameter given to the callback of nb (val) is - * "old_state", not the current state. The current state can be retrieved - * by looking at the third pameter (edev pointer)'s state value. - */ -int extcon_register_interest(struct extcon_specific_cable_nb *obj, - const char *extcon_name, const char *cable_name, - struct notifier_block *nb) -{ - unsigned long flags; - int ret; - - if (!obj || !cable_name || !nb) - return -EINVAL; - - if (extcon_name) { - obj->edev = extcon_get_extcon_dev(extcon_name); - if (!obj->edev) - return -ENODEV; - - obj->cable_index = find_cable_index_by_name(obj->edev, - cable_name); - if (obj->cable_index < 0) - return obj->cable_index; - - obj->user_nb = nb; - - spin_lock_irqsave(&obj->edev->lock, flags); - ret = raw_notifier_chain_register( - &obj->edev->nh[obj->cable_index], - obj->user_nb); - spin_unlock_irqrestore(&obj->edev->lock, flags); - } else { - struct class_dev_iter iter; - struct extcon_dev *extd; - struct device *dev; - - if (!extcon_class) - return -ENODEV; - class_dev_iter_init(&iter, extcon_class, NULL, NULL); - while ((dev = class_dev_iter_next(&iter))) { - extd = dev_get_drvdata(dev); - - if (find_cable_index_by_name(extd, cable_name) < 0) - continue; - - class_dev_iter_exit(&iter); - return extcon_register_interest(obj, extd->name, - cable_name, nb); - } - - ret = -ENODEV; - } - - return ret; -} -EXPORT_SYMBOL_GPL(extcon_register_interest); - -/** - * extcon_unregister_interest() - Unregister the notifier registered by - * extcon_register_interest(). - * @obj: the extcon_specific_cable_nb object returned by - * extcon_register_interest(). - */ -int extcon_unregister_interest(struct extcon_specific_cable_nb *obj) -{ - unsigned long flags; - int ret; - - if (!obj) - return -EINVAL; - - spin_lock_irqsave(&obj->edev->lock, flags); - ret = raw_notifier_chain_unregister( - &obj->edev->nh[obj->cable_index], obj->user_nb); - spin_unlock_irqrestore(&obj->edev->lock, flags); - - return ret; -} -EXPORT_SYMBOL_GPL(extcon_unregister_interest); - /** * extcon_register_notifier() - Register a notifiee to get notified by * any attach status changes from the extcon. @@ -582,14 +410,33 @@ int extcon_register_notifier(struct extcon_dev *edev, unsigned int id, unsigned long flags; int ret, idx; - if (!edev || !nb) + if (!nb) return -EINVAL; - idx = find_cable_index_by_id(edev, id); + if (edev) { + idx = find_cable_index_by_id(edev, id); - spin_lock_irqsave(&edev->lock, flags); - ret = raw_notifier_chain_register(&edev->nh[idx], nb); - spin_unlock_irqrestore(&edev->lock, flags); + spin_lock_irqsave(&edev->lock, flags); + ret = raw_notifier_chain_register(&edev->nh[idx], nb); + spin_unlock_irqrestore(&edev->lock, flags); + } else { + struct extcon_dev *extd; + + mutex_lock(&extcon_dev_list_lock); + list_for_each_entry(extd, &extcon_dev_list, entry) { + idx = find_cable_index_by_id(extd, id); + if (idx >= 0) + break; + } + mutex_unlock(&extcon_dev_list_lock); + + if (idx >= 0) { + edev = extd; + return extcon_register_notifier(extd, id, nb); + } else { + ret = -ENODEV; + } + } return ret; } -- cgit v1.2.3 From a05f44c89ee1151b0da3ddd43d9e57d8f15b2f20 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 23 Jun 2016 19:34:30 +0900 Subject: extcon: Check for incorrect connection type in notifier register If we call extcon_register_notifier() with the wrong cable type, it blows up with an oops instead of returning an error code. Let's be nice and fail gracefully given that the consumer might not know if the cable is supported by the extcon provider. Signed-off-by: Stephen Boyd Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/extcon/extcon.c') diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 4fef9ab4b148..b6408f015637 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -415,6 +415,8 @@ int extcon_register_notifier(struct extcon_dev *edev, unsigned int id, if (edev) { idx = find_cable_index_by_id(edev, id); + if (idx < 0) + return idx; spin_lock_irqsave(&edev->lock, flags); ret = raw_notifier_chain_register(&edev->nh[idx], nb); @@ -458,6 +460,8 @@ int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id, return -EINVAL; idx = find_cable_index_by_id(edev, id); + if (idx < 0) + return idx; spin_lock_irqsave(&edev->lock, flags); ret = raw_notifier_chain_unregister(&edev->nh[idx], nb); -- cgit v1.2.3 From 20f7b53dfc24e0caa984087691af82e442229680 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 27 Jun 2016 19:17:06 +0900 Subject: extcon: Move struct extcon_cable from header file to core This patch moves the struct extcon_cable because that should be only handled by extcon core. There are no reason to publish the internal structure. Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/extcon/extcon.c') diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index b6408f015637..b5fdb5d9dbad 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -77,6 +77,26 @@ static const char *extcon_name[] = { NULL, }; +/** + * struct extcon_cable - An internal data for each cable of extcon device. + * @edev: The extcon device + * @cable_index: Index of this cable in the edev + * @attr_g: Attribute group for the cable + * @attr_name: "name" sysfs entry + * @attr_state: "state" sysfs entry + * @attrs: Array pointing to attr_name and attr_state for attr_g + */ +struct extcon_cable { + struct extcon_dev *edev; + int cable_index; + + struct attribute_group attr_g; + struct device_attribute attr_name; + struct device_attribute attr_state; + + struct attribute *attrs[3]; /* to be fed to attr_g.attrs */ +}; + static struct class *extcon_class; #if defined(CONFIG_ANDROID) static struct class_compat *switch_class; -- cgit v1.2.3 From b225d00f3ad2d996f914790a0f6324a4efd18768 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 27 Jun 2016 19:28:04 +0900 Subject: extcon: Split out the resource-managed functions from extcon core This patch split out the resource-managed related functions from extcon core driver. Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon.c | 117 ------------------------------------------------ 1 file changed, 117 deletions(-) (limited to 'drivers/extcon/extcon.c') diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index b5fdb5d9dbad..862334e69cf1 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -564,66 +564,6 @@ void extcon_dev_free(struct extcon_dev *edev) } EXPORT_SYMBOL_GPL(extcon_dev_free); -static int devm_extcon_dev_match(struct device *dev, void *res, void *data) -{ - struct extcon_dev **r = res; - - if (WARN_ON(!r || !*r)) - return 0; - - return *r == data; -} - -static void devm_extcon_dev_release(struct device *dev, void *res) -{ - extcon_dev_free(*(struct extcon_dev **)res); -} - -/** - * devm_extcon_dev_allocate - Allocate managed extcon device - * @dev: device owning the extcon device being created - * @supported_cable: Array of supported extcon ending with EXTCON_NONE. - * If supported_cable is NULL, cable name related APIs - * are disabled. - * - * This function manages automatically the memory of extcon device using device - * resource management and simplify the control of freeing the memory of extcon - * device. - * - * Returns the pointer memory of allocated extcon_dev if success - * or ERR_PTR(err) if fail - */ -struct extcon_dev *devm_extcon_dev_allocate(struct device *dev, - const unsigned int *supported_cable) -{ - struct extcon_dev **ptr, *edev; - - ptr = devres_alloc(devm_extcon_dev_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); - - edev = extcon_dev_allocate(supported_cable); - if (IS_ERR(edev)) { - devres_free(ptr); - return edev; - } - - edev->dev.parent = dev; - - *ptr = edev; - devres_add(dev, ptr); - - return edev; -} -EXPORT_SYMBOL_GPL(devm_extcon_dev_allocate); - -void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev) -{ - WARN_ON(devres_release(dev, devm_extcon_dev_release, - devm_extcon_dev_match, edev)); -} -EXPORT_SYMBOL_GPL(devm_extcon_dev_free); - /** * extcon_dev_register() - Register a new extcon device * @edev : the new extcon device (should be allocated before calling) @@ -889,63 +829,6 @@ void extcon_dev_unregister(struct extcon_dev *edev) } EXPORT_SYMBOL_GPL(extcon_dev_unregister); -static void devm_extcon_dev_unreg(struct device *dev, void *res) -{ - extcon_dev_unregister(*(struct extcon_dev **)res); -} - -/** - * devm_extcon_dev_register() - Resource-managed extcon_dev_register() - * @dev: device to allocate extcon device - * @edev: the new extcon device to register - * - * Managed extcon_dev_register() function. If extcon device is attached with - * this function, that extcon device is automatically unregistered on driver - * detach. Internally this function calls extcon_dev_register() function. - * To get more information, refer that function. - * - * If extcon device is registered with this function and the device needs to be - * unregistered separately, devm_extcon_dev_unregister() should be used. - * - * Returns 0 if success or negaive error number if failure. - */ -int devm_extcon_dev_register(struct device *dev, struct extcon_dev *edev) -{ - struct extcon_dev **ptr; - int ret; - - ptr = devres_alloc(devm_extcon_dev_unreg, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return -ENOMEM; - - ret = extcon_dev_register(edev); - if (ret) { - devres_free(ptr); - return ret; - } - - *ptr = edev; - devres_add(dev, ptr); - - return 0; -} -EXPORT_SYMBOL_GPL(devm_extcon_dev_register); - -/** - * devm_extcon_dev_unregister() - Resource-managed extcon_dev_unregister() - * @dev: device the extcon belongs to - * @edev: the extcon device to unregister - * - * Unregister extcon device that is registered with devm_extcon_dev_register() - * function. - */ -void devm_extcon_dev_unregister(struct device *dev, struct extcon_dev *edev) -{ - WARN_ON(devres_release(dev, devm_extcon_dev_unreg, - devm_extcon_dev_match, edev)); -} -EXPORT_SYMBOL_GPL(devm_extcon_dev_unregister); - #ifdef CONFIG_OF /* * extcon_get_edev_by_phandle - Get the extcon device from devicetree -- cgit v1.2.3 From 5d5c4c139dd766dff903ba35d72fb3ec90022e91 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Fri, 1 Jul 2016 18:41:55 +0900 Subject: extcon: add missing of_node_put after calling of_parse_phandle of_node_put needs to be called when the device node which is got from of_parse_phandle has finished using. Signed-off-by: Peter Chen Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/extcon/extcon.c') diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 862334e69cf1..8682efc0f57b 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -861,10 +861,12 @@ struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index) list_for_each_entry(edev, &extcon_dev_list, entry) { if (edev->dev.parent && edev->dev.parent->of_node == node) { mutex_unlock(&extcon_dev_list_lock); + of_node_put(node); return edev; } } mutex_unlock(&extcon_dev_list_lock); + of_node_put(node); return ERR_PTR(-EPROBE_DEFER); } -- cgit v1.2.3