0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "extcon.h"
0010
0011 static int devm_extcon_dev_match(struct device *dev, void *res, void *data)
0012 {
0013 struct extcon_dev **r = res;
0014
0015 if (WARN_ON(!r || !*r))
0016 return 0;
0017
0018 return *r == data;
0019 }
0020
0021 static void devm_extcon_dev_release(struct device *dev, void *res)
0022 {
0023 extcon_dev_free(*(struct extcon_dev **)res);
0024 }
0025
0026
0027 static void devm_extcon_dev_unreg(struct device *dev, void *res)
0028 {
0029 extcon_dev_unregister(*(struct extcon_dev **)res);
0030 }
0031
0032 struct extcon_dev_notifier_devres {
0033 struct extcon_dev *edev;
0034 unsigned int id;
0035 struct notifier_block *nb;
0036 };
0037
0038 static void devm_extcon_dev_notifier_unreg(struct device *dev, void *res)
0039 {
0040 struct extcon_dev_notifier_devres *this = res;
0041
0042 extcon_unregister_notifier(this->edev, this->id, this->nb);
0043 }
0044
0045 static void devm_extcon_dev_notifier_all_unreg(struct device *dev, void *res)
0046 {
0047 struct extcon_dev_notifier_devres *this = res;
0048
0049 extcon_unregister_notifier_all(this->edev, this->nb);
0050 }
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
0066 const unsigned int *supported_cable)
0067 {
0068 struct extcon_dev **ptr, *edev;
0069
0070 ptr = devres_alloc(devm_extcon_dev_release, sizeof(*ptr), GFP_KERNEL);
0071 if (!ptr)
0072 return ERR_PTR(-ENOMEM);
0073
0074 edev = extcon_dev_allocate(supported_cable);
0075 if (IS_ERR(edev)) {
0076 devres_free(ptr);
0077 return edev;
0078 }
0079
0080 edev->dev.parent = dev;
0081
0082 *ptr = edev;
0083 devres_add(dev, ptr);
0084
0085 return edev;
0086 }
0087 EXPORT_SYMBOL_GPL(devm_extcon_dev_allocate);
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev)
0098 {
0099 WARN_ON(devres_release(dev, devm_extcon_dev_release,
0100 devm_extcon_dev_match, edev));
0101 }
0102 EXPORT_SYMBOL_GPL(devm_extcon_dev_free);
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 int devm_extcon_dev_register(struct device *dev, struct extcon_dev *edev)
0119 {
0120 struct extcon_dev **ptr;
0121 int ret;
0122
0123 ptr = devres_alloc(devm_extcon_dev_unreg, sizeof(*ptr), GFP_KERNEL);
0124 if (!ptr)
0125 return -ENOMEM;
0126
0127 ret = extcon_dev_register(edev);
0128 if (ret) {
0129 devres_free(ptr);
0130 return ret;
0131 }
0132
0133 *ptr = edev;
0134 devres_add(dev, ptr);
0135
0136 return 0;
0137 }
0138 EXPORT_SYMBOL_GPL(devm_extcon_dev_register);
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148 void devm_extcon_dev_unregister(struct device *dev, struct extcon_dev *edev)
0149 {
0150 WARN_ON(devres_release(dev, devm_extcon_dev_unreg,
0151 devm_extcon_dev_match, edev));
0152 }
0153 EXPORT_SYMBOL_GPL(devm_extcon_dev_unregister);
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172 int devm_extcon_register_notifier(struct device *dev, struct extcon_dev *edev,
0173 unsigned int id, struct notifier_block *nb)
0174 {
0175 struct extcon_dev_notifier_devres *ptr;
0176 int ret;
0177
0178 ptr = devres_alloc(devm_extcon_dev_notifier_unreg, sizeof(*ptr),
0179 GFP_KERNEL);
0180 if (!ptr)
0181 return -ENOMEM;
0182
0183 ret = extcon_register_notifier(edev, id, nb);
0184 if (ret) {
0185 devres_free(ptr);
0186 return ret;
0187 }
0188
0189 ptr->edev = edev;
0190 ptr->id = id;
0191 ptr->nb = nb;
0192 devres_add(dev, ptr);
0193
0194 return 0;
0195 }
0196 EXPORT_SYMBOL(devm_extcon_register_notifier);
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 void devm_extcon_unregister_notifier(struct device *dev,
0207 struct extcon_dev *edev, unsigned int id,
0208 struct notifier_block *nb)
0209 {
0210 WARN_ON(devres_release(dev, devm_extcon_dev_notifier_unreg,
0211 devm_extcon_dev_match, edev));
0212 }
0213 EXPORT_SYMBOL(devm_extcon_unregister_notifier);
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228 int devm_extcon_register_notifier_all(struct device *dev, struct extcon_dev *edev,
0229 struct notifier_block *nb)
0230 {
0231 struct extcon_dev_notifier_devres *ptr;
0232 int ret;
0233
0234 ptr = devres_alloc(devm_extcon_dev_notifier_all_unreg, sizeof(*ptr),
0235 GFP_KERNEL);
0236 if (!ptr)
0237 return -ENOMEM;
0238
0239 ret = extcon_register_notifier_all(edev, nb);
0240 if (ret) {
0241 devres_free(ptr);
0242 return ret;
0243 }
0244
0245 ptr->edev = edev;
0246 ptr->nb = nb;
0247 devres_add(dev, ptr);
0248
0249 return 0;
0250 }
0251 EXPORT_SYMBOL(devm_extcon_register_notifier_all);
0252
0253
0254
0255
0256
0257
0258
0259
0260 void devm_extcon_unregister_notifier_all(struct device *dev,
0261 struct extcon_dev *edev,
0262 struct notifier_block *nb)
0263 {
0264 WARN_ON(devres_release(dev, devm_extcon_dev_notifier_all_unreg,
0265 devm_extcon_dev_match, edev));
0266 }
0267 EXPORT_SYMBOL(devm_extcon_unregister_notifier_all);