Lines Matching +full:half +full:- +full:length

1 // SPDX-License-Identifier: GPL-2.0-only
16 #include "nd-core.h"
21 INIT_LIST_HEAD(&badrange->list); in badrange_init()
22 spin_lock_init(&badrange->lock); in badrange_init()
27 struct badrange_entry *bre, u64 addr, u64 length) in append_badrange_entry() argument
29 lockdep_assert_held(&badrange->lock); in append_badrange_entry()
30 bre->start = addr; in append_badrange_entry()
31 bre->length = length; in append_badrange_entry()
32 list_add_tail(&bre->list, &badrange->list); in append_badrange_entry()
36 u64 addr, u64 length, gfp_t flags) in alloc_and_append_badrange_entry() argument
42 return -ENOMEM; in alloc_and_append_badrange_entry()
44 append_badrange_entry(badrange, bre, addr, length); in alloc_and_append_badrange_entry()
48 static int add_badrange(struct badrange *badrange, u64 addr, u64 length) in add_badrange() argument
52 spin_unlock(&badrange->lock); in add_badrange()
54 spin_lock(&badrange->lock); in add_badrange()
56 if (list_empty(&badrange->list)) { in add_badrange()
58 return -ENOMEM; in add_badrange()
59 append_badrange_entry(badrange, bre_new, addr, length); in add_badrange()
68 list_for_each_entry(bre, &badrange->list, list) in add_badrange()
69 if (bre->start == addr) { in add_badrange()
70 /* If length has changed, update this list entry */ in add_badrange()
71 if (bre->length != length) in add_badrange()
72 bre->length = length; in add_badrange()
78 * If not a duplicate or a simple length update, add the entry as is, in add_badrange()
83 return -ENOMEM; in add_badrange()
84 append_badrange_entry(badrange, bre_new, addr, length); in add_badrange()
89 int badrange_add(struct badrange *badrange, u64 addr, u64 length) in badrange_add() argument
93 spin_lock(&badrange->lock); in badrange_add()
94 rc = add_badrange(badrange, addr, length); in badrange_add()
95 spin_unlock(&badrange->lock); in badrange_add()
104 struct list_head *badrange_list = &badrange->list; in badrange_forget()
105 u64 clr_end = start + len - 1; in badrange_forget()
108 spin_lock(&badrange->lock); in badrange_forget()
112 * [bre->start, bre_end] is the badrange_list entry we're comparing in badrange_forget()
114 * to be modified (update either start or length), deleted, or in badrange_forget()
119 u64 bre_end = bre->start + bre->length - 1; in badrange_forget()
124 if (bre->start > clr_end) in badrange_forget()
127 if ((bre->start >= start) && (bre_end <= clr_end)) { in badrange_forget()
128 list_del(&bre->list); in badrange_forget()
133 if ((start <= bre->start) && (clr_end > bre->start)) { in badrange_forget()
134 bre->length -= clr_end - bre->start + 1; in badrange_forget()
135 bre->start = clr_end + 1; in badrange_forget()
138 /* Adjust bre->length for partial clearing at the tail end */ in badrange_forget()
139 if ((bre->start < start) && (bre_end <= clr_end)) { in badrange_forget()
140 /* bre->start remains the same */ in badrange_forget()
141 bre->length = start - bre->start; in badrange_forget()
146 * two by modifying the current entry to represent one half of in badrange_forget()
147 * the split, and adding a new entry for the second half. in badrange_forget()
149 if ((bre->start < start) && (bre_end > clr_end)) { in badrange_forget()
151 u64 new_len = bre_end - new_start + 1; in badrange_forget()
153 /* Add new entry covering the right half */ in badrange_forget()
156 /* Adjust this entry to cover the left half */ in badrange_forget()
157 bre->length = start - bre->start; in badrange_forget()
161 spin_unlock(&badrange->lock); in badrange_forget()
167 dev_dbg(bb->dev, "Found a bad range (0x%llx, 0x%llx)\n", in set_badblock()
171 dev_info_once(bb->dev, "%s: failed for sector %llx\n", in set_badblock()
176 * __add_badblock_range() - Convert a physical address range to bad sectors
196 num_sectors = end_sector - start_sector; in __add_badblock_range()
206 remaining -= done; in __add_badblock_range()
218 if (list_empty(&badrange->list)) in badblocks_populate()
221 list_for_each_entry(bre, &badrange->list, list) { in badblocks_populate()
222 u64 bre_end = bre->start + bre->length - 1; in badblocks_populate()
225 if (bre_end < range->start) in badblocks_populate()
227 if (bre->start > range->end) in badblocks_populate()
230 if (bre->start >= range->start) { in badblocks_populate()
231 u64 start = bre->start; in badblocks_populate()
234 if (bre_end <= range->end) in badblocks_populate()
235 len = bre->length; in badblocks_populate()
237 len = range->start + range_len(range) in badblocks_populate()
238 - bre->start; in badblocks_populate()
239 __add_badblock_range(bb, start - range->start, len); in badblocks_populate()
246 if (bre->start < range->start) { in badblocks_populate()
249 if (bre_end < range->end) in badblocks_populate()
250 len = bre->start + bre->length - range->start; in badblocks_populate()
259 * nvdimm_badblocks_populate() - Convert a list of badranges to badblocks
267 * and add badblocks entries for all matching sub-ranges
274 if (!is_memory(&nd_region->dev)) { in nvdimm_badblocks_populate()
275 dev_WARN_ONCE(&nd_region->dev, 1, in nvdimm_badblocks_populate()
279 nvdimm_bus = walk_to_nvdimm_bus(&nd_region->dev); in nvdimm_badblocks_populate()
281 nvdimm_bus_lock(&nvdimm_bus->dev); in nvdimm_badblocks_populate()
282 badblocks_populate(&nvdimm_bus->badrange, bb, range); in nvdimm_badblocks_populate()
283 nvdimm_bus_unlock(&nvdimm_bus->dev); in nvdimm_badblocks_populate()