aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/badblocks.c48
-rw-r--r--include/linux/badblocks.h14
2 files changed, 48 insertions, 14 deletions
diff --git a/block/badblocks.c b/block/badblocks.c
index 37e5c0a2ef69..7be53cb1cc3c 100644
--- a/block/badblocks.c
+++ b/block/badblocks.c
@@ -17,6 +17,7 @@
17 17
18#include <linux/badblocks.h> 18#include <linux/badblocks.h>
19#include <linux/seqlock.h> 19#include <linux/seqlock.h>
20#include <linux/device.h>
20#include <linux/kernel.h> 21#include <linux/kernel.h>
21#include <linux/module.h> 22#include <linux/module.h>
22#include <linux/stddef.h> 23#include <linux/stddef.h>
@@ -522,24 +523,20 @@ ssize_t badblocks_store(struct badblocks *bb, const char *page, size_t len,
522} 523}
523EXPORT_SYMBOL_GPL(badblocks_store); 524EXPORT_SYMBOL_GPL(badblocks_store);
524 525
525/** 526static int __badblocks_init(struct device *dev, struct badblocks *bb,
526 * badblocks_init() - initialize the badblocks structure 527 int enable)
527 * @bb: the badblocks structure that holds all badblock information
528 * @enable: weather to enable badblocks accounting
529 *
530 * Return:
531 * 0: success
532 * -ve errno: on error
533 */
534int badblocks_init(struct badblocks *bb, int enable)
535{ 528{
529 bb->dev = dev;
536 bb->count = 0; 530 bb->count = 0;
537 if (enable) 531 if (enable)
538 bb->shift = 0; 532 bb->shift = 0;
539 else 533 else
540 bb->shift = -1; 534 bb->shift = -1;
541 bb->page = kzalloc(PAGE_SIZE, GFP_KERNEL); 535 if (dev)
542 if (bb->page == (u64 *)0) { 536 bb->page = devm_kzalloc(dev, PAGE_SIZE, GFP_KERNEL);
537 else
538 bb->page = kzalloc(PAGE_SIZE, GFP_KERNEL);
539 if (!bb->page) {
543 bb->shift = -1; 540 bb->shift = -1;
544 return -ENOMEM; 541 return -ENOMEM;
545 } 542 }
@@ -547,8 +544,30 @@ int badblocks_init(struct badblocks *bb, int enable)
547 544
548 return 0; 545 return 0;
549} 546}
547
548/**
549 * badblocks_init() - initialize the badblocks structure
550 * @bb: the badblocks structure that holds all badblock information
551 * @enable: weather to enable badblocks accounting
552 *
553 * Return:
554 * 0: success
555 * -ve errno: on error
556 */
557int badblocks_init(struct badblocks *bb, int enable)
558{
559 return __badblocks_init(NULL, bb, enable);
560}
550EXPORT_SYMBOL_GPL(badblocks_init); 561EXPORT_SYMBOL_GPL(badblocks_init);
551 562
563int devm_init_badblocks(struct device *dev, struct badblocks *bb)
564{
565 if (!bb)
566 return -EINVAL;
567 return __badblocks_init(dev, bb, 1);
568}
569EXPORT_SYMBOL_GPL(devm_init_badblocks);
570
552/** 571/**
553 * badblocks_exit() - free the badblocks structure 572 * badblocks_exit() - free the badblocks structure
554 * @bb: the badblocks structure that holds all badblock information 573 * @bb: the badblocks structure that holds all badblock information
@@ -557,7 +576,10 @@ void badblocks_exit(struct badblocks *bb)
557{ 576{
558 if (!bb) 577 if (!bb)
559 return; 578 return;
560 kfree(bb->page); 579 if (bb->dev)
580 devm_kfree(bb->dev, bb->page);
581 else
582 kfree(bb->page);
561 bb->page = NULL; 583 bb->page = NULL;
562} 584}
563EXPORT_SYMBOL_GPL(badblocks_exit); 585EXPORT_SYMBOL_GPL(badblocks_exit);
diff --git a/include/linux/badblocks.h b/include/linux/badblocks.h
index 2d98c026c57f..c3bdf8c59480 100644
--- a/include/linux/badblocks.h
+++ b/include/linux/badblocks.h
@@ -2,6 +2,7 @@
2#define _LINUX_BADBLOCKS_H 2#define _LINUX_BADBLOCKS_H
3 3
4#include <linux/seqlock.h> 4#include <linux/seqlock.h>
5#include <linux/device.h>
5#include <linux/kernel.h> 6#include <linux/kernel.h>
6#include <linux/stddef.h> 7#include <linux/stddef.h>
7#include <linux/types.h> 8#include <linux/types.h>
@@ -23,6 +24,7 @@
23#define MAX_BADBLOCKS (PAGE_SIZE/8) 24#define MAX_BADBLOCKS (PAGE_SIZE/8)
24 25
25struct badblocks { 26struct badblocks {
27 struct device *dev; /* set by devm_init_badblocks */
26 int count; /* count of bad blocks */ 28 int count; /* count of bad blocks */
27 int unacked_exist; /* there probably are unacknowledged 29 int unacked_exist; /* there probably are unacknowledged
28 * bad blocks. This is only cleared 30 * bad blocks. This is only cleared
@@ -49,5 +51,15 @@ ssize_t badblocks_store(struct badblocks *bb, const char *page, size_t len,
49 int unack); 51 int unack);
50int badblocks_init(struct badblocks *bb, int enable); 52int badblocks_init(struct badblocks *bb, int enable);
51void badblocks_exit(struct badblocks *bb); 53void badblocks_exit(struct badblocks *bb);
52 54struct device;
55int devm_init_badblocks(struct device *dev, struct badblocks *bb);
56static inline void devm_exit_badblocks(struct device *dev, struct badblocks *bb)
57{
58 if (bb->dev != dev) {
59 dev_WARN_ONCE(dev, 1, "%s: badblocks instance not associated\n",
60 __func__);
61 return;
62 }
63 badblocks_exit(bb);
64}
53#endif 65#endif