aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Reichel <sre@kernel.org>2017-04-13 19:41:45 -0400
committerSebastian Reichel <sre@kernel.org>2017-04-13 19:41:45 -0400
commitddaa00ee63e184d86d3963ce3014ae04a6a4fce2 (patch)
treea82fdd1f6b9bb070e3ca8a6ab03cf2c1a420e4d0
parent61489b0f9fa835cd2fef67ae26790cdf64b6b1c7 (diff)
parent815429b39d94c64f6d05eed9e7c1a9bdfdd5bd70 (diff)
Merge remote-tracking branch 'chanwoo-extcon/ib-extcon-4.12' into psy-next
-rw-r--r--drivers/extcon/devres.c61
-rw-r--r--drivers/extcon/extcon.c66
-rw-r--r--drivers/extcon/extcon.h3
-rw-r--r--include/linux/extcon.h21
4 files changed, 146 insertions, 5 deletions
diff --git a/drivers/extcon/devres.c b/drivers/extcon/devres.c
index b40eb1805927..186fd735eb28 100644
--- a/drivers/extcon/devres.c
+++ b/drivers/extcon/devres.c
@@ -50,6 +50,13 @@ static void devm_extcon_dev_notifier_unreg(struct device *dev, void *res)
50 extcon_unregister_notifier(this->edev, this->id, this->nb); 50 extcon_unregister_notifier(this->edev, this->id, this->nb);
51} 51}
52 52
53static void devm_extcon_dev_notifier_all_unreg(struct device *dev, void *res)
54{
55 struct extcon_dev_notifier_devres *this = res;
56
57 extcon_unregister_notifier_all(this->edev, this->nb);
58}
59
53/** 60/**
54 * devm_extcon_dev_allocate - Allocate managed extcon device 61 * devm_extcon_dev_allocate - Allocate managed extcon device
55 * @dev: device owning the extcon device being created 62 * @dev: device owning the extcon device being created
@@ -214,3 +221,57 @@ void devm_extcon_unregister_notifier(struct device *dev,
214 devm_extcon_dev_match, edev)); 221 devm_extcon_dev_match, edev));
215} 222}
216EXPORT_SYMBOL(devm_extcon_unregister_notifier); 223EXPORT_SYMBOL(devm_extcon_unregister_notifier);
224
225/**
226 * devm_extcon_register_notifier_all()
227 * - Resource-managed extcon_register_notifier_all()
228 * @dev: device to allocate extcon device
229 * @edev: the extcon device that has the external connecotr.
230 * @nb: a notifier block to be registered.
231 *
232 * This function manages automatically the notifier of extcon device using
233 * device resource management and simplify the control of unregistering
234 * the notifier of extcon device. To get more information, refer that function.
235 *
236 * Returns 0 if success or negaive error number if failure.
237 */
238int devm_extcon_register_notifier_all(struct device *dev, struct extcon_dev *edev,
239 struct notifier_block *nb)
240{
241 struct extcon_dev_notifier_devres *ptr;
242 int ret;
243
244 ptr = devres_alloc(devm_extcon_dev_notifier_all_unreg, sizeof(*ptr),
245 GFP_KERNEL);
246 if (!ptr)
247 return -ENOMEM;
248
249 ret = extcon_register_notifier_all(edev, nb);
250 if (ret) {
251 devres_free(ptr);
252 return ret;
253 }
254
255 ptr->edev = edev;
256 ptr->nb = nb;
257 devres_add(dev, ptr);
258
259 return 0;
260}
261EXPORT_SYMBOL(devm_extcon_register_notifier_all);
262
263/**
264 * devm_extcon_unregister_notifier_all()
265 * - Resource-managed extcon_unregister_notifier_all()
266 * @dev: device to allocate extcon device
267 * @edev: the extcon device that has the external connecotr.
268 * @nb: a notifier block to be registered.
269 */
270void devm_extcon_unregister_notifier_all(struct device *dev,
271 struct extcon_dev *edev,
272 struct notifier_block *nb)
273{
274 WARN_ON(devres_release(dev, devm_extcon_dev_notifier_all_unreg,
275 devm_extcon_dev_match, edev));
276}
277EXPORT_SYMBOL(devm_extcon_unregister_notifier_all);
diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c
index 09ac5e70c2f3..e7750545469f 100644
--- a/drivers/extcon/extcon.c
+++ b/drivers/extcon/extcon.c
@@ -448,8 +448,19 @@ int extcon_sync(struct extcon_dev *edev, unsigned int id)
448 spin_lock_irqsave(&edev->lock, flags); 448 spin_lock_irqsave(&edev->lock, flags);
449 449
450 state = !!(edev->state & BIT(index)); 450 state = !!(edev->state & BIT(index));
451
452 /*
453 * Call functions in a raw notifier chain for the specific one
454 * external connector.
455 */
451 raw_notifier_call_chain(&edev->nh[index], state, edev); 456 raw_notifier_call_chain(&edev->nh[index], state, edev);
452 457
458 /*
459 * Call functions in a raw notifier chain for the all supported
460 * external connectors.
461 */
462 raw_notifier_call_chain(&edev->nh_all, state, edev);
463
453 /* This could be in interrupt handler */ 464 /* This could be in interrupt handler */
454 prop_buf = (char *)get_zeroed_page(GFP_ATOMIC); 465 prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
455 if (!prop_buf) { 466 if (!prop_buf) {
@@ -954,6 +965,59 @@ int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id,
954} 965}
955EXPORT_SYMBOL_GPL(extcon_unregister_notifier); 966EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
956 967
968/**
969 * extcon_register_notifier_all() - Register a notifier block for all connectors
970 * @edev: the extcon device that has the external connecotr.
971 * @nb: a notifier block to be registered.
972 *
973 * This fucntion registers a notifier block in order to receive the state
974 * change of all supported external connectors from extcon device.
975 * And The second parameter given to the callback of nb (val) is
976 * the current state and third parameter is the edev pointer.
977 *
978 * Returns 0 if success or error number if fail
979 */
980int extcon_register_notifier_all(struct extcon_dev *edev,
981 struct notifier_block *nb)
982{
983 unsigned long flags;
984 int ret;
985
986 if (!edev || !nb)
987 return -EINVAL;
988
989 spin_lock_irqsave(&edev->lock, flags);
990 ret = raw_notifier_chain_register(&edev->nh_all, nb);
991 spin_unlock_irqrestore(&edev->lock, flags);
992
993 return ret;
994}
995EXPORT_SYMBOL_GPL(extcon_register_notifier_all);
996
997/**
998 * extcon_unregister_notifier_all() - Unregister a notifier block from extcon.
999 * @edev: the extcon device that has the external connecotr.
1000 * @nb: a notifier block to be registered.
1001 *
1002 * Returns 0 if success or error number if fail
1003 */
1004int extcon_unregister_notifier_all(struct extcon_dev *edev,
1005 struct notifier_block *nb)
1006{
1007 unsigned long flags;
1008 int ret;
1009
1010 if (!edev || !nb)
1011 return -EINVAL;
1012
1013 spin_lock_irqsave(&edev->lock, flags);
1014 ret = raw_notifier_chain_unregister(&edev->nh_all, nb);
1015 spin_unlock_irqrestore(&edev->lock, flags);
1016
1017 return ret;
1018}
1019EXPORT_SYMBOL_GPL(extcon_unregister_notifier_all);
1020
957static struct attribute *extcon_attrs[] = { 1021static struct attribute *extcon_attrs[] = {
958 &dev_attr_state.attr, 1022 &dev_attr_state.attr,
959 &dev_attr_name.attr, 1023 &dev_attr_name.attr,
@@ -1212,6 +1276,8 @@ int extcon_dev_register(struct extcon_dev *edev)
1212 for (index = 0; index < edev->max_supported; index++) 1276 for (index = 0; index < edev->max_supported; index++)
1213 RAW_INIT_NOTIFIER_HEAD(&edev->nh[index]); 1277 RAW_INIT_NOTIFIER_HEAD(&edev->nh[index]);
1214 1278
1279 RAW_INIT_NOTIFIER_HEAD(&edev->nh_all);
1280
1215 dev_set_drvdata(&edev->dev, edev); 1281 dev_set_drvdata(&edev->dev, edev);
1216 edev->state = 0; 1282 edev->state = 0;
1217 1283
diff --git a/drivers/extcon/extcon.h b/drivers/extcon/extcon.h
index 993ddccafe11..dddddcfa0587 100644
--- a/drivers/extcon/extcon.h
+++ b/drivers/extcon/extcon.h
@@ -21,6 +21,8 @@
21 * @dev: Device of this extcon. 21 * @dev: Device of this extcon.
22 * @state: Attach/detach state of this extcon. Do not provide at 22 * @state: Attach/detach state of this extcon. Do not provide at
23 * register-time. 23 * register-time.
24 * @nh_all: Notifier for the state change events for all supported
25 * external connectors from this extcon.
24 * @nh: Notifier for the state change events from this extcon 26 * @nh: Notifier for the state change events from this extcon
25 * @entry: To support list of extcon devices so that users can 27 * @entry: To support list of extcon devices so that users can
26 * search for extcon devices based on the extcon name. 28 * search for extcon devices based on the extcon name.
@@ -43,6 +45,7 @@ struct extcon_dev {
43 45
44 /* Internal data. Please do not set. */ 46 /* Internal data. Please do not set. */
45 struct device dev; 47 struct device dev;
48 struct raw_notifier_head nh_all;
46 struct raw_notifier_head *nh; 49 struct raw_notifier_head *nh;
47 struct list_head entry; 50 struct list_head entry;
48 int max_supported; 51 int max_supported;
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index 7010fb01a81a..7e206a9f88db 100644
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
@@ -236,11 +236,11 @@ extern int extcon_set_property_capability(struct extcon_dev *edev,
236 unsigned int id, unsigned int prop); 236 unsigned int id, unsigned int prop);
237 237
238/* 238/*
239 * Following APIs are to monitor every action of a notifier. 239 * Following APIs are to monitor the status change of the external connectors.
240 * Registrar gets notified for every external port of a connection device. 240 * extcon_register_notifier(*edev, id, *nb) : Register a notifier block
241 * Probably this could be used to debug an action of notifier; however, 241 * for specific external connector of the extcon.
242 * we do not recommend to use this for normal 'notifiee' device drivers who 242 * extcon_register_notifier_all(*edev, *nb) : Register a notifier block
243 * want to be notified by a specific external port of the notifier. 243 * for all supported external connectors of the extcon.
244 */ 244 */
245extern int extcon_register_notifier(struct extcon_dev *edev, unsigned int id, 245extern int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
246 struct notifier_block *nb); 246 struct notifier_block *nb);
@@ -253,6 +253,17 @@ extern void devm_extcon_unregister_notifier(struct device *dev,
253 struct extcon_dev *edev, unsigned int id, 253 struct extcon_dev *edev, unsigned int id,
254 struct notifier_block *nb); 254 struct notifier_block *nb);
255 255
256extern int extcon_register_notifier_all(struct extcon_dev *edev,
257 struct notifier_block *nb);
258extern int extcon_unregister_notifier_all(struct extcon_dev *edev,
259 struct notifier_block *nb);
260extern int devm_extcon_register_notifier_all(struct device *dev,
261 struct extcon_dev *edev,
262 struct notifier_block *nb);
263extern void devm_extcon_unregister_notifier_all(struct device *dev,
264 struct extcon_dev *edev,
265 struct notifier_block *nb);
266
256/* 267/*
257 * Following API get the extcon device from devicetree. 268 * Following API get the extcon device from devicetree.
258 * This function use phandle of devicetree to get extcon device directly. 269 * This function use phandle of devicetree to get extcon device directly.