diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-10 14:35:36 -0500 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-10 14:35:36 -0500 |
| commit | 4ba24fef3eb3b142197135223b90ced2f319cd53 (patch) | |
| tree | a20c125b27740ec7b4c761b11d801108e1b316b2 /kernel/resource.c | |
| parent | 47c1ffb2b6b630894e9a16442611c056ab21c057 (diff) | |
| parent | 98a4a59ee31a12105a2b84f5b8b515ac2cb208ef (diff) | |
Merge branch 'next' into for-linus
Prepare first round of input updates for 3.20.
Diffstat (limited to 'kernel/resource.c')
| -rw-r--r-- | kernel/resource.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/kernel/resource.c b/kernel/resource.c index 60c5a3856ab7..0bcebffc4e77 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
| @@ -491,6 +491,42 @@ int __weak page_is_ram(unsigned long pfn) | |||
| 491 | } | 491 | } |
| 492 | EXPORT_SYMBOL_GPL(page_is_ram); | 492 | EXPORT_SYMBOL_GPL(page_is_ram); |
| 493 | 493 | ||
| 494 | /* | ||
| 495 | * Search for a resouce entry that fully contains the specified region. | ||
| 496 | * If found, return 1 if it is RAM, 0 if not. | ||
| 497 | * If not found, or region is not fully contained, return -1 | ||
| 498 | * | ||
| 499 | * Used by the ioremap functions to ensure the user is not remapping RAM and is | ||
| 500 | * a vast speed up over walking through the resource table page by page. | ||
| 501 | */ | ||
| 502 | int region_is_ram(resource_size_t start, unsigned long size) | ||
| 503 | { | ||
| 504 | struct resource *p; | ||
| 505 | resource_size_t end = start + size - 1; | ||
| 506 | int flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
| 507 | const char *name = "System RAM"; | ||
| 508 | int ret = -1; | ||
| 509 | |||
| 510 | read_lock(&resource_lock); | ||
| 511 | for (p = iomem_resource.child; p ; p = p->sibling) { | ||
| 512 | if (end < p->start) | ||
| 513 | continue; | ||
| 514 | |||
| 515 | if (p->start <= start && end <= p->end) { | ||
| 516 | /* resource fully contains region */ | ||
| 517 | if ((p->flags != flags) || strcmp(p->name, name)) | ||
| 518 | ret = 0; | ||
| 519 | else | ||
| 520 | ret = 1; | ||
| 521 | break; | ||
| 522 | } | ||
| 523 | if (p->end < start) | ||
| 524 | break; /* not found */ | ||
| 525 | } | ||
| 526 | read_unlock(&resource_lock); | ||
| 527 | return ret; | ||
| 528 | } | ||
| 529 | |||
| 494 | void __weak arch_remove_reservations(struct resource *avail) | 530 | void __weak arch_remove_reservations(struct resource *avail) |
| 495 | { | 531 | { |
| 496 | } | 532 | } |
| @@ -1245,6 +1281,76 @@ int release_mem_region_adjustable(struct resource *parent, | |||
| 1245 | /* | 1281 | /* |
| 1246 | * Managed region resource | 1282 | * Managed region resource |
| 1247 | */ | 1283 | */ |
| 1284 | static void devm_resource_release(struct device *dev, void *ptr) | ||
| 1285 | { | ||
| 1286 | struct resource **r = ptr; | ||
| 1287 | |||
| 1288 | release_resource(*r); | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | /** | ||
| 1292 | * devm_request_resource() - request and reserve an I/O or memory resource | ||
| 1293 | * @dev: device for which to request the resource | ||
| 1294 | * @root: root of the resource tree from which to request the resource | ||
| 1295 | * @new: descriptor of the resource to request | ||
| 1296 | * | ||
| 1297 | * This is a device-managed version of request_resource(). There is usually | ||
| 1298 | * no need to release resources requested by this function explicitly since | ||
| 1299 | * that will be taken care of when the device is unbound from its driver. | ||
| 1300 | * If for some reason the resource needs to be released explicitly, because | ||
| 1301 | * of ordering issues for example, drivers must call devm_release_resource() | ||
| 1302 | * rather than the regular release_resource(). | ||
| 1303 | * | ||
| 1304 | * When a conflict is detected between any existing resources and the newly | ||
| 1305 | * requested resource, an error message will be printed. | ||
| 1306 | * | ||
| 1307 | * Returns 0 on success or a negative error code on failure. | ||
| 1308 | */ | ||
| 1309 | int devm_request_resource(struct device *dev, struct resource *root, | ||
| 1310 | struct resource *new) | ||
| 1311 | { | ||
| 1312 | struct resource *conflict, **ptr; | ||
| 1313 | |||
| 1314 | ptr = devres_alloc(devm_resource_release, sizeof(*ptr), GFP_KERNEL); | ||
| 1315 | if (!ptr) | ||
| 1316 | return -ENOMEM; | ||
| 1317 | |||
| 1318 | *ptr = new; | ||
| 1319 | |||
| 1320 | conflict = request_resource_conflict(root, new); | ||
| 1321 | if (conflict) { | ||
| 1322 | dev_err(dev, "resource collision: %pR conflicts with %s %pR\n", | ||
| 1323 | new, conflict->name, conflict); | ||
| 1324 | devres_free(ptr); | ||
| 1325 | return -EBUSY; | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | devres_add(dev, ptr); | ||
| 1329 | return 0; | ||
| 1330 | } | ||
| 1331 | EXPORT_SYMBOL(devm_request_resource); | ||
| 1332 | |||
| 1333 | static int devm_resource_match(struct device *dev, void *res, void *data) | ||
| 1334 | { | ||
| 1335 | struct resource **ptr = res; | ||
| 1336 | |||
| 1337 | return *ptr == data; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | /** | ||
| 1341 | * devm_release_resource() - release a previously requested resource | ||
| 1342 | * @dev: device for which to release the resource | ||
| 1343 | * @new: descriptor of the resource to release | ||
| 1344 | * | ||
| 1345 | * Releases a resource previously requested using devm_request_resource(). | ||
| 1346 | */ | ||
| 1347 | void devm_release_resource(struct device *dev, struct resource *new) | ||
| 1348 | { | ||
| 1349 | WARN_ON(devres_release(dev, devm_resource_release, devm_resource_match, | ||
| 1350 | new)); | ||
| 1351 | } | ||
| 1352 | EXPORT_SYMBOL(devm_release_resource); | ||
| 1353 | |||
| 1248 | struct region_devres { | 1354 | struct region_devres { |
| 1249 | struct resource *parent; | 1355 | struct resource *parent; |
| 1250 | resource_size_t start; | 1356 | resource_size_t start; |
