@@ -45,9 +45,25 @@ static struct nd_region *to_region(struct pmem_device *pmem)
45
45
return to_nd_region (to_dev (pmem )-> parent );
46
46
}
47
47
48
- static void hwpoison_clear (struct pmem_device * pmem ,
49
- phys_addr_t phys , unsigned int len )
48
+ static phys_addr_t to_phys (struct pmem_device * pmem , phys_addr_t offset )
50
49
{
50
+ return pmem -> phys_addr + offset ;
51
+ }
52
+
53
+ static sector_t to_sect (struct pmem_device * pmem , phys_addr_t offset )
54
+ {
55
+ return (offset - pmem -> data_offset ) >> SECTOR_SHIFT ;
56
+ }
57
+
58
+ static phys_addr_t to_offset (struct pmem_device * pmem , sector_t sector )
59
+ {
60
+ return (sector << SECTOR_SHIFT ) + pmem -> data_offset ;
61
+ }
62
+
63
+ static void pmem_mkpage_present (struct pmem_device * pmem , phys_addr_t offset ,
64
+ unsigned int len )
65
+ {
66
+ phys_addr_t phys = to_phys (pmem , offset );
51
67
unsigned long pfn_start , pfn_end , pfn ;
52
68
53
69
/* only pmem in the linear map supports HWPoison */
@@ -69,33 +85,40 @@ static void hwpoison_clear(struct pmem_device *pmem,
69
85
}
70
86
}
71
87
72
- static blk_status_t pmem_clear_poison (struct pmem_device * pmem ,
73
- phys_addr_t offset , unsigned int len )
88
+ static void pmem_clear_bb (struct pmem_device * pmem , sector_t sector , long blks )
74
89
{
75
- struct device * dev = to_dev (pmem );
76
- sector_t sector ;
77
- long cleared ;
78
- blk_status_t rc = BLK_STS_OK ;
90
+ if (blks == 0 )
91
+ return ;
92
+ badblocks_clear (& pmem -> bb , sector , blks );
93
+ if (pmem -> bb_state )
94
+ sysfs_notify_dirent (pmem -> bb_state );
95
+ }
79
96
80
- sector = (offset - pmem -> data_offset ) / 512 ;
97
+ static long __pmem_clear_poison (struct pmem_device * pmem ,
98
+ phys_addr_t offset , unsigned int len )
99
+ {
100
+ phys_addr_t phys = to_phys (pmem , offset );
101
+ long cleared = nvdimm_clear_poison (to_dev (pmem ), phys , len );
81
102
82
- cleared = nvdimm_clear_poison (dev , pmem -> phys_addr + offset , len );
83
- if (cleared < len )
84
- rc = BLK_STS_IOERR ;
85
- if (cleared > 0 && cleared / 512 ) {
86
- hwpoison_clear (pmem , pmem -> phys_addr + offset , cleared );
87
- cleared /= 512 ;
88
- dev_dbg (dev , "%#llx clear %ld sector%s\n" ,
89
- (unsigned long long ) sector , cleared ,
90
- cleared > 1 ? "s" : "" );
91
- badblocks_clear (& pmem -> bb , sector , cleared );
92
- if (pmem -> bb_state )
93
- sysfs_notify_dirent (pmem -> bb_state );
103
+ if (cleared > 0 ) {
104
+ pmem_mkpage_present (pmem , offset , cleared );
105
+ arch_invalidate_pmem (pmem -> virt_addr + offset , len );
94
106
}
107
+ return cleared ;
108
+ }
95
109
96
- arch_invalidate_pmem (pmem -> virt_addr + offset , len );
110
+ static blk_status_t pmem_clear_poison (struct pmem_device * pmem ,
111
+ phys_addr_t offset , unsigned int len )
112
+ {
113
+ long cleared = __pmem_clear_poison (pmem , offset , len );
97
114
98
- return rc ;
115
+ if (cleared < 0 )
116
+ return BLK_STS_IOERR ;
117
+
118
+ pmem_clear_bb (pmem , to_sect (pmem , offset ), cleared >> SECTOR_SHIFT );
119
+ if (cleared < len )
120
+ return BLK_STS_IOERR ;
121
+ return BLK_STS_OK ;
99
122
}
100
123
101
124
static void write_pmem (void * pmem_addr , struct page * page ,
@@ -143,7 +166,7 @@ static blk_status_t pmem_do_read(struct pmem_device *pmem,
143
166
sector_t sector , unsigned int len )
144
167
{
145
168
blk_status_t rc ;
146
- phys_addr_t pmem_off = sector * 512 + pmem -> data_offset ;
169
+ phys_addr_t pmem_off = to_offset ( pmem , sector ) ;
147
170
void * pmem_addr = pmem -> virt_addr + pmem_off ;
148
171
149
172
if (unlikely (is_bad_pmem (& pmem -> bb , sector , len )))
@@ -158,7 +181,7 @@ static blk_status_t pmem_do_write(struct pmem_device *pmem,
158
181
struct page * page , unsigned int page_off ,
159
182
sector_t sector , unsigned int len )
160
183
{
161
- phys_addr_t pmem_off = sector * 512 + pmem -> data_offset ;
184
+ phys_addr_t pmem_off = to_offset ( pmem , sector ) ;
162
185
void * pmem_addr = pmem -> virt_addr + pmem_off ;
163
186
164
187
if (unlikely (is_bad_pmem (& pmem -> bb , sector , len ))) {
0 commit comments