@@ -45,9 +45,25 @@ static struct nd_region *to_region(struct pmem_device *pmem)
4545 return to_nd_region (to_dev (pmem )-> parent );
4646}
4747
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 )
5049{
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 );
5167 unsigned long pfn_start , pfn_end , pfn ;
5268
5369 /* only pmem in the linear map supports HWPoison */
@@ -69,33 +85,40 @@ static void hwpoison_clear(struct pmem_device *pmem,
6985 }
7086}
7187
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 )
7489{
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+ }
7996
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 );
81102
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 );
94106 }
107+ return cleared ;
108+ }
95109
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 );
97114
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 ;
99122}
100123
101124static void write_pmem (void * pmem_addr , struct page * page ,
@@ -143,7 +166,7 @@ static blk_status_t pmem_do_read(struct pmem_device *pmem,
143166 sector_t sector , unsigned int len )
144167{
145168 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 ) ;
147170 void * pmem_addr = pmem -> virt_addr + pmem_off ;
148171
149172 if (unlikely (is_bad_pmem (& pmem -> bb , sector , len )))
@@ -158,7 +181,7 @@ static blk_status_t pmem_do_write(struct pmem_device *pmem,
158181 struct page * page , unsigned int page_off ,
159182 sector_t sector , unsigned int len )
160183{
161- phys_addr_t pmem_off = sector * 512 + pmem -> data_offset ;
184+ phys_addr_t pmem_off = to_offset ( pmem , sector ) ;
162185 void * pmem_addr = pmem -> virt_addr + pmem_off ;
163186
164187 if (unlikely (is_bad_pmem (& pmem -> bb , sector , len ))) {
0 commit comments