diff options
author | Thierry Reding <treding@nvidia.com> | 2014-08-01 08:15:10 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2014-09-04 16:41:43 -0400 |
commit | 8d38821cbcf51292cd5a23469d03bd38932a3ba9 (patch) | |
tree | a41f35c52ba3826dc4099a8bf24630a410633f62 /kernel/resource.c | |
parent | 52addcf9d6669fa439387610bc65c92fa0980cef (diff) |
resources: Add device-managed request/release_resource()
Provide device-managed implementations of the request_resource() and
release_resource() functions. Upon failure to request a resource, the new
devm_request_resource() function will output an error message for
consistent error reporting.
Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/resource.c')
-rw-r--r-- | kernel/resource.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/kernel/resource.c b/kernel/resource.c index da14b8d09296..ca24f19f9d18 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
@@ -1248,6 +1248,76 @@ int release_mem_region_adjustable(struct resource *parent, | |||
1248 | /* | 1248 | /* |
1249 | * Managed region resource | 1249 | * Managed region resource |
1250 | */ | 1250 | */ |
1251 | static void devm_resource_release(struct device *dev, void *ptr) | ||
1252 | { | ||
1253 | struct resource **r = ptr; | ||
1254 | |||
1255 | release_resource(*r); | ||
1256 | } | ||
1257 | |||
1258 | /** | ||
1259 | * devm_request_resource() - request and reserve an I/O or memory resource | ||
1260 | * @dev: device for which to request the resource | ||
1261 | * @root: root of the resource tree from which to request the resource | ||
1262 | * @new: descriptor of the resource to request | ||
1263 | * | ||
1264 | * This is a device-managed version of request_resource(). There is usually | ||
1265 | * no need to release resources requested by this function explicitly since | ||
1266 | * that will be taken care of when the device is unbound from its driver. | ||
1267 | * If for some reason the resource needs to be released explicitly, because | ||
1268 | * of ordering issues for example, drivers must call devm_release_resource() | ||
1269 | * rather than the regular release_resource(). | ||
1270 | * | ||
1271 | * When a conflict is detected between any existing resources and the newly | ||
1272 | * requested resource, an error message will be printed. | ||
1273 | * | ||
1274 | * Returns 0 on success or a negative error code on failure. | ||
1275 | */ | ||
1276 | int devm_request_resource(struct device *dev, struct resource *root, | ||
1277 | struct resource *new) | ||
1278 | { | ||
1279 | struct resource *conflict, **ptr; | ||
1280 | |||
1281 | ptr = devres_alloc(devm_resource_release, sizeof(*ptr), GFP_KERNEL); | ||
1282 | if (!ptr) | ||
1283 | return -ENOMEM; | ||
1284 | |||
1285 | *ptr = new; | ||
1286 | |||
1287 | conflict = request_resource_conflict(root, new); | ||
1288 | if (conflict) { | ||
1289 | dev_err(dev, "resource collision: %pR conflicts with %s %pR\n", | ||
1290 | new, conflict->name, conflict); | ||
1291 | devres_free(ptr); | ||
1292 | return -EBUSY; | ||
1293 | } | ||
1294 | |||
1295 | devres_add(dev, ptr); | ||
1296 | return 0; | ||
1297 | } | ||
1298 | EXPORT_SYMBOL(devm_request_resource); | ||
1299 | |||
1300 | static int devm_resource_match(struct device *dev, void *res, void *data) | ||
1301 | { | ||
1302 | struct resource **ptr = res; | ||
1303 | |||
1304 | return *ptr == data; | ||
1305 | } | ||
1306 | |||
1307 | /** | ||
1308 | * devm_release_resource() - release a previously requested resource | ||
1309 | * @dev: device for which to release the resource | ||
1310 | * @new: descriptor of the resource to release | ||
1311 | * | ||
1312 | * Releases a resource previously requested using devm_request_resource(). | ||
1313 | */ | ||
1314 | void devm_release_resource(struct device *dev, struct resource *new) | ||
1315 | { | ||
1316 | WARN_ON(devres_release(dev, devm_resource_release, devm_resource_match, | ||
1317 | new)); | ||
1318 | } | ||
1319 | EXPORT_SYMBOL(devm_release_resource); | ||
1320 | |||
1251 | struct region_devres { | 1321 | struct region_devres { |
1252 | struct resource *parent; | 1322 | struct resource *parent; |
1253 | resource_size_t start; | 1323 | resource_size_t start; |