Loading drivers/extcon/devres.c +61 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,13 @@ static void devm_extcon_dev_notifier_unreg(struct device *dev, void *res) extcon_unregister_notifier(this->edev, this->id, this->nb); } static void devm_extcon_dev_notifier_all_unreg(struct device *dev, void *res) { struct extcon_dev_notifier_devres *this = res; extcon_unregister_notifier_all(this->edev, this->nb); } /** * devm_extcon_dev_allocate - Allocate managed extcon device * @dev: device owning the extcon device being created Loading Loading @@ -214,3 +221,57 @@ void devm_extcon_unregister_notifier(struct device *dev, devm_extcon_dev_match, edev)); } EXPORT_SYMBOL(devm_extcon_unregister_notifier); /** * devm_extcon_register_notifier_all() * - Resource-managed extcon_register_notifier_all() * @dev: device to allocate extcon device * @edev: the extcon device that has the external connecotr. * @nb: a notifier block to be registered. * * This function manages automatically the notifier of extcon device using * device resource management and simplify the control of unregistering * the notifier of extcon device. To get more information, refer that function. * * Returns 0 if success or negaive error number if failure. */ int devm_extcon_register_notifier_all(struct device *dev, struct extcon_dev *edev, struct notifier_block *nb) { struct extcon_dev_notifier_devres *ptr; int ret; ptr = devres_alloc(devm_extcon_dev_notifier_all_unreg, sizeof(*ptr), GFP_KERNEL); if (!ptr) return -ENOMEM; ret = extcon_register_notifier_all(edev, nb); if (ret) { devres_free(ptr); return ret; } ptr->edev = edev; ptr->nb = nb; devres_add(dev, ptr); return 0; } EXPORT_SYMBOL(devm_extcon_register_notifier_all); /** * devm_extcon_unregister_notifier_all() * - Resource-managed extcon_unregister_notifier_all() * @dev: device to allocate extcon device * @edev: the extcon device that has the external connecotr. * @nb: a notifier block to be registered. */ void devm_extcon_unregister_notifier_all(struct device *dev, struct extcon_dev *edev, struct notifier_block *nb) { WARN_ON(devres_release(dev, devm_extcon_dev_notifier_all_unreg, devm_extcon_dev_match, edev)); } EXPORT_SYMBOL(devm_extcon_unregister_notifier_all); drivers/extcon/extcon.c +66 −0 Original line number Diff line number Diff line Loading @@ -448,8 +448,19 @@ int extcon_sync(struct extcon_dev *edev, unsigned int id) spin_lock_irqsave(&edev->lock, flags); state = !!(edev->state & BIT(index)); /* * Call functions in a raw notifier chain for the specific one * external connector. */ raw_notifier_call_chain(&edev->nh[index], state, edev); /* * Call functions in a raw notifier chain for the all supported * external connectors. */ raw_notifier_call_chain(&edev->nh_all, state, edev); /* This could be in interrupt handler */ prop_buf = (char *)get_zeroed_page(GFP_ATOMIC); if (!prop_buf) { Loading Loading @@ -954,6 +965,59 @@ int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id, } EXPORT_SYMBOL_GPL(extcon_unregister_notifier); /** * extcon_register_notifier_all() - Register a notifier block for all connectors * @edev: the extcon device that has the external connecotr. * @nb: a notifier block to be registered. * * This fucntion registers a notifier block in order to receive the state * change of all supported external connectors from extcon device. * And The second parameter given to the callback of nb (val) is * the current state and third parameter is the edev pointer. * * Returns 0 if success or error number if fail */ int extcon_register_notifier_all(struct extcon_dev *edev, struct notifier_block *nb) { unsigned long flags; int ret; if (!edev || !nb) return -EINVAL; spin_lock_irqsave(&edev->lock, flags); ret = raw_notifier_chain_register(&edev->nh_all, nb); spin_unlock_irqrestore(&edev->lock, flags); return ret; } EXPORT_SYMBOL_GPL(extcon_register_notifier_all); /** * extcon_unregister_notifier_all() - Unregister a notifier block from extcon. * @edev: the extcon device that has the external connecotr. * @nb: a notifier block to be registered. * * Returns 0 if success or error number if fail */ int extcon_unregister_notifier_all(struct extcon_dev *edev, struct notifier_block *nb) { unsigned long flags; int ret; if (!edev || !nb) return -EINVAL; spin_lock_irqsave(&edev->lock, flags); ret = raw_notifier_chain_unregister(&edev->nh_all, nb); spin_unlock_irqrestore(&edev->lock, flags); return ret; } EXPORT_SYMBOL_GPL(extcon_unregister_notifier_all); static struct attribute *extcon_attrs[] = { &dev_attr_state.attr, &dev_attr_name.attr, Loading Loading @@ -1212,6 +1276,8 @@ int extcon_dev_register(struct extcon_dev *edev) for (index = 0; index < edev->max_supported; index++) RAW_INIT_NOTIFIER_HEAD(&edev->nh[index]); RAW_INIT_NOTIFIER_HEAD(&edev->nh_all); dev_set_drvdata(&edev->dev, edev); edev->state = 0; Loading drivers/extcon/extcon.h +3 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ * @dev: Device of this extcon. * @state: Attach/detach state of this extcon. Do not provide at * register-time. * @nh_all: Notifier for the state change events for all supported * external connectors from this extcon. * @nh: Notifier for the state change events from this extcon * @entry: To support list of extcon devices so that users can * search for extcon devices based on the extcon name. Loading @@ -43,6 +45,7 @@ struct extcon_dev { /* Internal data. Please do not set. */ struct device dev; struct raw_notifier_head nh_all; struct raw_notifier_head *nh; struct list_head entry; int max_supported; Loading include/linux/extcon.h +16 −5 Original line number Diff line number Diff line Loading @@ -236,11 +236,11 @@ extern int extcon_set_property_capability(struct extcon_dev *edev, unsigned int id, unsigned int prop); /* * Following APIs are to monitor every action of a notifier. * Registrar gets notified for every external port of a connection device. * Probably this could be used to debug an action of notifier; however, * we do not recommend to use this for normal 'notifiee' device drivers who * want to be notified by a specific external port of the notifier. * Following APIs are to monitor the status change of the external connectors. * extcon_register_notifier(*edev, id, *nb) : Register a notifier block * for specific external connector of the extcon. * extcon_register_notifier_all(*edev, *nb) : Register a notifier block * for all supported external connectors of the extcon. */ extern int extcon_register_notifier(struct extcon_dev *edev, unsigned int id, struct notifier_block *nb); Loading @@ -253,6 +253,17 @@ extern void devm_extcon_unregister_notifier(struct device *dev, struct extcon_dev *edev, unsigned int id, struct notifier_block *nb); extern int extcon_register_notifier_all(struct extcon_dev *edev, struct notifier_block *nb); extern int extcon_unregister_notifier_all(struct extcon_dev *edev, struct notifier_block *nb); extern int devm_extcon_register_notifier_all(struct device *dev, struct extcon_dev *edev, struct notifier_block *nb); extern void devm_extcon_unregister_notifier_all(struct device *dev, struct extcon_dev *edev, struct notifier_block *nb); /* * Following API get the extcon device from devicetree. * This function use phandle of devicetree to get extcon device directly. Loading Loading
drivers/extcon/devres.c +61 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,13 @@ static void devm_extcon_dev_notifier_unreg(struct device *dev, void *res) extcon_unregister_notifier(this->edev, this->id, this->nb); } static void devm_extcon_dev_notifier_all_unreg(struct device *dev, void *res) { struct extcon_dev_notifier_devres *this = res; extcon_unregister_notifier_all(this->edev, this->nb); } /** * devm_extcon_dev_allocate - Allocate managed extcon device * @dev: device owning the extcon device being created Loading Loading @@ -214,3 +221,57 @@ void devm_extcon_unregister_notifier(struct device *dev, devm_extcon_dev_match, edev)); } EXPORT_SYMBOL(devm_extcon_unregister_notifier); /** * devm_extcon_register_notifier_all() * - Resource-managed extcon_register_notifier_all() * @dev: device to allocate extcon device * @edev: the extcon device that has the external connecotr. * @nb: a notifier block to be registered. * * This function manages automatically the notifier of extcon device using * device resource management and simplify the control of unregistering * the notifier of extcon device. To get more information, refer that function. * * Returns 0 if success or negaive error number if failure. */ int devm_extcon_register_notifier_all(struct device *dev, struct extcon_dev *edev, struct notifier_block *nb) { struct extcon_dev_notifier_devres *ptr; int ret; ptr = devres_alloc(devm_extcon_dev_notifier_all_unreg, sizeof(*ptr), GFP_KERNEL); if (!ptr) return -ENOMEM; ret = extcon_register_notifier_all(edev, nb); if (ret) { devres_free(ptr); return ret; } ptr->edev = edev; ptr->nb = nb; devres_add(dev, ptr); return 0; } EXPORT_SYMBOL(devm_extcon_register_notifier_all); /** * devm_extcon_unregister_notifier_all() * - Resource-managed extcon_unregister_notifier_all() * @dev: device to allocate extcon device * @edev: the extcon device that has the external connecotr. * @nb: a notifier block to be registered. */ void devm_extcon_unregister_notifier_all(struct device *dev, struct extcon_dev *edev, struct notifier_block *nb) { WARN_ON(devres_release(dev, devm_extcon_dev_notifier_all_unreg, devm_extcon_dev_match, edev)); } EXPORT_SYMBOL(devm_extcon_unregister_notifier_all);
drivers/extcon/extcon.c +66 −0 Original line number Diff line number Diff line Loading @@ -448,8 +448,19 @@ int extcon_sync(struct extcon_dev *edev, unsigned int id) spin_lock_irqsave(&edev->lock, flags); state = !!(edev->state & BIT(index)); /* * Call functions in a raw notifier chain for the specific one * external connector. */ raw_notifier_call_chain(&edev->nh[index], state, edev); /* * Call functions in a raw notifier chain for the all supported * external connectors. */ raw_notifier_call_chain(&edev->nh_all, state, edev); /* This could be in interrupt handler */ prop_buf = (char *)get_zeroed_page(GFP_ATOMIC); if (!prop_buf) { Loading Loading @@ -954,6 +965,59 @@ int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id, } EXPORT_SYMBOL_GPL(extcon_unregister_notifier); /** * extcon_register_notifier_all() - Register a notifier block for all connectors * @edev: the extcon device that has the external connecotr. * @nb: a notifier block to be registered. * * This fucntion registers a notifier block in order to receive the state * change of all supported external connectors from extcon device. * And The second parameter given to the callback of nb (val) is * the current state and third parameter is the edev pointer. * * Returns 0 if success or error number if fail */ int extcon_register_notifier_all(struct extcon_dev *edev, struct notifier_block *nb) { unsigned long flags; int ret; if (!edev || !nb) return -EINVAL; spin_lock_irqsave(&edev->lock, flags); ret = raw_notifier_chain_register(&edev->nh_all, nb); spin_unlock_irqrestore(&edev->lock, flags); return ret; } EXPORT_SYMBOL_GPL(extcon_register_notifier_all); /** * extcon_unregister_notifier_all() - Unregister a notifier block from extcon. * @edev: the extcon device that has the external connecotr. * @nb: a notifier block to be registered. * * Returns 0 if success or error number if fail */ int extcon_unregister_notifier_all(struct extcon_dev *edev, struct notifier_block *nb) { unsigned long flags; int ret; if (!edev || !nb) return -EINVAL; spin_lock_irqsave(&edev->lock, flags); ret = raw_notifier_chain_unregister(&edev->nh_all, nb); spin_unlock_irqrestore(&edev->lock, flags); return ret; } EXPORT_SYMBOL_GPL(extcon_unregister_notifier_all); static struct attribute *extcon_attrs[] = { &dev_attr_state.attr, &dev_attr_name.attr, Loading Loading @@ -1212,6 +1276,8 @@ int extcon_dev_register(struct extcon_dev *edev) for (index = 0; index < edev->max_supported; index++) RAW_INIT_NOTIFIER_HEAD(&edev->nh[index]); RAW_INIT_NOTIFIER_HEAD(&edev->nh_all); dev_set_drvdata(&edev->dev, edev); edev->state = 0; Loading
drivers/extcon/extcon.h +3 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ * @dev: Device of this extcon. * @state: Attach/detach state of this extcon. Do not provide at * register-time. * @nh_all: Notifier for the state change events for all supported * external connectors from this extcon. * @nh: Notifier for the state change events from this extcon * @entry: To support list of extcon devices so that users can * search for extcon devices based on the extcon name. Loading @@ -43,6 +45,7 @@ struct extcon_dev { /* Internal data. Please do not set. */ struct device dev; struct raw_notifier_head nh_all; struct raw_notifier_head *nh; struct list_head entry; int max_supported; Loading
include/linux/extcon.h +16 −5 Original line number Diff line number Diff line Loading @@ -236,11 +236,11 @@ extern int extcon_set_property_capability(struct extcon_dev *edev, unsigned int id, unsigned int prop); /* * Following APIs are to monitor every action of a notifier. * Registrar gets notified for every external port of a connection device. * Probably this could be used to debug an action of notifier; however, * we do not recommend to use this for normal 'notifiee' device drivers who * want to be notified by a specific external port of the notifier. * Following APIs are to monitor the status change of the external connectors. * extcon_register_notifier(*edev, id, *nb) : Register a notifier block * for specific external connector of the extcon. * extcon_register_notifier_all(*edev, *nb) : Register a notifier block * for all supported external connectors of the extcon. */ extern int extcon_register_notifier(struct extcon_dev *edev, unsigned int id, struct notifier_block *nb); Loading @@ -253,6 +253,17 @@ extern void devm_extcon_unregister_notifier(struct device *dev, struct extcon_dev *edev, unsigned int id, struct notifier_block *nb); extern int extcon_register_notifier_all(struct extcon_dev *edev, struct notifier_block *nb); extern int extcon_unregister_notifier_all(struct extcon_dev *edev, struct notifier_block *nb); extern int devm_extcon_register_notifier_all(struct device *dev, struct extcon_dev *edev, struct notifier_block *nb); extern void devm_extcon_unregister_notifier_all(struct device *dev, struct extcon_dev *edev, struct notifier_block *nb); /* * Following API get the extcon device from devicetree. * This function use phandle of devicetree to get extcon device directly. Loading