diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/core.c | 5 | ||||
-rw-r--r-- | drivers/base/dd.c | 3 | ||||
-rw-r--r-- | drivers/base/memory.c | 62 | ||||
-rw-r--r-- | drivers/base/platform.c | 54 |
4 files changed, 83 insertions, 41 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index bc8729d603a7..82c865452c70 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -1764,8 +1764,8 @@ void device_shutdown(void) | |||
1764 | 1764 | ||
1765 | #ifdef CONFIG_PRINTK | 1765 | #ifdef CONFIG_PRINTK |
1766 | 1766 | ||
1767 | static int __dev_printk(const char *level, const struct device *dev, | 1767 | int __dev_printk(const char *level, const struct device *dev, |
1768 | struct va_format *vaf) | 1768 | struct va_format *vaf) |
1769 | { | 1769 | { |
1770 | if (!dev) | 1770 | if (!dev) |
1771 | return printk("%s(NULL device *): %pV", level, vaf); | 1771 | return printk("%s(NULL device *): %pV", level, vaf); |
@@ -1773,6 +1773,7 @@ static int __dev_printk(const char *level, const struct device *dev, | |||
1773 | return printk("%s%s %s: %pV", | 1773 | return printk("%s%s %s: %pV", |
1774 | level, dev_driver_string(dev), dev_name(dev), vaf); | 1774 | level, dev_driver_string(dev), dev_name(dev), vaf); |
1775 | } | 1775 | } |
1776 | EXPORT_SYMBOL(__dev_printk); | ||
1776 | 1777 | ||
1777 | int dev_printk(const char *level, const struct device *dev, | 1778 | int dev_printk(const char *level, const struct device *dev, |
1778 | const char *fmt, ...) | 1779 | const char *fmt, ...) |
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 6658da743c3a..142e3d600f14 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -147,6 +147,9 @@ probe_failed: | |||
147 | printk(KERN_WARNING | 147 | printk(KERN_WARNING |
148 | "%s: probe of %s failed with error %d\n", | 148 | "%s: probe of %s failed with error %d\n", |
149 | drv->name, dev_name(dev), ret); | 149 | drv->name, dev_name(dev), ret); |
150 | } else { | ||
151 | pr_debug("%s: probe of %s rejects match %d\n", | ||
152 | drv->name, dev_name(dev), ret); | ||
150 | } | 153 | } |
151 | /* | 154 | /* |
152 | * Ignore errors returned by ->probe so that the next driver can try | 155 | * Ignore errors returned by ->probe so that the next driver can try |
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 2840ed4668c1..8272d92d22c0 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
@@ -224,13 +224,48 @@ int memory_isolate_notify(unsigned long val, void *v) | |||
224 | } | 224 | } |
225 | 225 | ||
226 | /* | 226 | /* |
227 | * The probe routines leave the pages reserved, just as the bootmem code does. | ||
228 | * Make sure they're still that way. | ||
229 | */ | ||
230 | static bool pages_correctly_reserved(unsigned long start_pfn, | ||
231 | unsigned long nr_pages) | ||
232 | { | ||
233 | int i, j; | ||
234 | struct page *page; | ||
235 | unsigned long pfn = start_pfn; | ||
236 | |||
237 | /* | ||
238 | * memmap between sections is not contiguous except with | ||
239 | * SPARSEMEM_VMEMMAP. We lookup the page once per section | ||
240 | * and assume memmap is contiguous within each section | ||
241 | */ | ||
242 | for (i = 0; i < sections_per_block; i++, pfn += PAGES_PER_SECTION) { | ||
243 | if (WARN_ON_ONCE(!pfn_valid(pfn))) | ||
244 | return false; | ||
245 | page = pfn_to_page(pfn); | ||
246 | |||
247 | for (j = 0; j < PAGES_PER_SECTION; j++) { | ||
248 | if (PageReserved(page + j)) | ||
249 | continue; | ||
250 | |||
251 | printk(KERN_WARNING "section number %ld page number %d " | ||
252 | "not reserved, was it already online?\n", | ||
253 | pfn_to_section_nr(pfn), j); | ||
254 | |||
255 | return false; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | return true; | ||
260 | } | ||
261 | |||
262 | /* | ||
227 | * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is | 263 | * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is |
228 | * OK to have direct references to sparsemem variables in here. | 264 | * OK to have direct references to sparsemem variables in here. |
229 | */ | 265 | */ |
230 | static int | 266 | static int |
231 | memory_block_action(unsigned long phys_index, unsigned long action) | 267 | memory_block_action(unsigned long phys_index, unsigned long action) |
232 | { | 268 | { |
233 | int i; | ||
234 | unsigned long start_pfn, start_paddr; | 269 | unsigned long start_pfn, start_paddr; |
235 | unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; | 270 | unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; |
236 | struct page *first_page; | 271 | struct page *first_page; |
@@ -238,26 +273,13 @@ memory_block_action(unsigned long phys_index, unsigned long action) | |||
238 | 273 | ||
239 | first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT); | 274 | first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT); |
240 | 275 | ||
241 | /* | ||
242 | * The probe routines leave the pages reserved, just | ||
243 | * as the bootmem code does. Make sure they're still | ||
244 | * that way. | ||
245 | */ | ||
246 | if (action == MEM_ONLINE) { | ||
247 | for (i = 0; i < nr_pages; i++) { | ||
248 | if (PageReserved(first_page+i)) | ||
249 | continue; | ||
250 | |||
251 | printk(KERN_WARNING "section number %ld page number %d " | ||
252 | "not reserved, was it already online?\n", | ||
253 | phys_index, i); | ||
254 | return -EBUSY; | ||
255 | } | ||
256 | } | ||
257 | |||
258 | switch (action) { | 276 | switch (action) { |
259 | case MEM_ONLINE: | 277 | case MEM_ONLINE: |
260 | start_pfn = page_to_pfn(first_page); | 278 | start_pfn = page_to_pfn(first_page); |
279 | |||
280 | if (!pages_correctly_reserved(start_pfn, nr_pages)) | ||
281 | return -EBUSY; | ||
282 | |||
261 | ret = online_pages(start_pfn, nr_pages); | 283 | ret = online_pages(start_pfn, nr_pages); |
262 | break; | 284 | break; |
263 | case MEM_OFFLINE: | 285 | case MEM_OFFLINE: |
@@ -380,9 +402,13 @@ memory_probe_store(struct class *class, struct class_attribute *attr, | |||
380 | u64 phys_addr; | 402 | u64 phys_addr; |
381 | int nid; | 403 | int nid; |
382 | int i, ret; | 404 | int i, ret; |
405 | unsigned long pages_per_block = PAGES_PER_SECTION * sections_per_block; | ||
383 | 406 | ||
384 | phys_addr = simple_strtoull(buf, NULL, 0); | 407 | phys_addr = simple_strtoull(buf, NULL, 0); |
385 | 408 | ||
409 | if (phys_addr & ((pages_per_block << PAGE_SHIFT) - 1)) | ||
410 | return -EINVAL; | ||
411 | |||
386 | for (i = 0; i < sections_per_block; i++) { | 412 | for (i = 0; i < sections_per_block; i++) { |
387 | nid = memory_add_physaddr_to_nid(phys_addr); | 413 | nid = memory_add_physaddr_to_nid(phys_addr); |
388 | ret = add_memory(nid, phys_addr, | 414 | ret = add_memory(nid, phys_addr, |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 99a5272d7c2f..7a24895543e7 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -375,52 +375,64 @@ void platform_device_unregister(struct platform_device *pdev) | |||
375 | EXPORT_SYMBOL_GPL(platform_device_unregister); | 375 | EXPORT_SYMBOL_GPL(platform_device_unregister); |
376 | 376 | ||
377 | /** | 377 | /** |
378 | * platform_device_register_resndata - add a platform-level device with | 378 | * platform_device_register_full - add a platform-level device with |
379 | * resources and platform-specific data | 379 | * resources and platform-specific data |
380 | * | 380 | * |
381 | * @parent: parent device for the device we're adding | 381 | * @pdevinfo: data used to create device |
382 | * @name: base name of the device we're adding | ||
383 | * @id: instance id | ||
384 | * @res: set of resources that needs to be allocated for the device | ||
385 | * @num: number of resources | ||
386 | * @data: platform specific data for this platform device | ||
387 | * @size: size of platform specific data | ||
388 | * | 382 | * |
389 | * Returns &struct platform_device pointer on success, or ERR_PTR() on error. | 383 | * Returns &struct platform_device pointer on success, or ERR_PTR() on error. |
390 | */ | 384 | */ |
391 | struct platform_device *platform_device_register_resndata( | 385 | struct platform_device *platform_device_register_full( |
392 | struct device *parent, | 386 | struct platform_device_info *pdevinfo) |
393 | const char *name, int id, | ||
394 | const struct resource *res, unsigned int num, | ||
395 | const void *data, size_t size) | ||
396 | { | 387 | { |
397 | int ret = -ENOMEM; | 388 | int ret = -ENOMEM; |
398 | struct platform_device *pdev; | 389 | struct platform_device *pdev; |
399 | 390 | ||
400 | pdev = platform_device_alloc(name, id); | 391 | pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id); |
401 | if (!pdev) | 392 | if (!pdev) |
402 | goto err; | 393 | goto err_alloc; |
403 | 394 | ||
404 | pdev->dev.parent = parent; | 395 | pdev->dev.parent = pdevinfo->parent; |
396 | |||
397 | if (pdevinfo->dma_mask) { | ||
398 | /* | ||
399 | * This memory isn't freed when the device is put, | ||
400 | * I don't have a nice idea for that though. Conceptually | ||
401 | * dma_mask in struct device should not be a pointer. | ||
402 | * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 | ||
403 | */ | ||
404 | pdev->dev.dma_mask = | ||
405 | kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); | ||
406 | if (!pdev->dev.dma_mask) | ||
407 | goto err; | ||
408 | |||
409 | *pdev->dev.dma_mask = pdevinfo->dma_mask; | ||
410 | pdev->dev.coherent_dma_mask = pdevinfo->dma_mask; | ||
411 | } | ||
405 | 412 | ||
406 | ret = platform_device_add_resources(pdev, res, num); | 413 | ret = platform_device_add_resources(pdev, |
414 | pdevinfo->res, pdevinfo->num_res); | ||
407 | if (ret) | 415 | if (ret) |
408 | goto err; | 416 | goto err; |
409 | 417 | ||
410 | ret = platform_device_add_data(pdev, data, size); | 418 | ret = platform_device_add_data(pdev, |
419 | pdevinfo->data, pdevinfo->size_data); | ||
411 | if (ret) | 420 | if (ret) |
412 | goto err; | 421 | goto err; |
413 | 422 | ||
414 | ret = platform_device_add(pdev); | 423 | ret = platform_device_add(pdev); |
415 | if (ret) { | 424 | if (ret) { |
416 | err: | 425 | err: |
426 | kfree(pdev->dev.dma_mask); | ||
427 | |||
428 | err_alloc: | ||
417 | platform_device_put(pdev); | 429 | platform_device_put(pdev); |
418 | return ERR_PTR(ret); | 430 | return ERR_PTR(ret); |
419 | } | 431 | } |
420 | 432 | ||
421 | return pdev; | 433 | return pdev; |
422 | } | 434 | } |
423 | EXPORT_SYMBOL_GPL(platform_device_register_resndata); | 435 | EXPORT_SYMBOL_GPL(platform_device_register_full); |
424 | 436 | ||
425 | static int platform_drv_probe(struct device *_dev) | 437 | static int platform_drv_probe(struct device *_dev) |
426 | { | 438 | { |
@@ -614,7 +626,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
614 | return rc; | 626 | return rc; |
615 | 627 | ||
616 | add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX, | 628 | add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX, |
617 | (pdev->id_entry) ? pdev->id_entry->name : pdev->name); | 629 | pdev->name); |
618 | return 0; | 630 | return 0; |
619 | } | 631 | } |
620 | 632 | ||