Lines Matching full:bb

457 static int prev_by_hint(struct badblocks *bb, sector_t s, int hint)  in prev_by_hint()  argument
460 u64 *p = bb->page; in prev_by_hint()
463 while ((hint < hint_end) && ((hint + 1) <= bb->count) && in prev_by_hint()
465 if ((hint + 1) == bb->count || BB_OFFSET(p[hint + 1]) > s) { in prev_by_hint()
481 static int prev_badblocks(struct badblocks *bb, struct badblocks_context *bad, in prev_badblocks() argument
489 if (!bb->count) in prev_badblocks()
493 ret = prev_by_hint(bb, s, hint); in prev_badblocks()
499 hi = bb->count; in prev_badblocks()
500 p = bb->page; in prev_badblocks()
534 static bool can_merge_behind(struct badblocks *bb, in can_merge_behind() argument
539 u64 *p = bb->page; in can_merge_behind()
554 static int behind_merge(struct badblocks *bb, struct badblocks_context *bad, in behind_merge() argument
559 u64 *p = bb->page; in behind_merge()
579 static bool can_merge_front(struct badblocks *bb, int prev, in can_merge_front() argument
583 u64 *p = bb->page; in can_merge_front()
597 static int front_merge(struct badblocks *bb, int prev, struct badblocks_context *bad) in front_merge() argument
601 u64 *p = bb->page; in front_merge()
610 if ((prev + 1) < bb->count && in front_merge()
633 static bool can_combine_front(struct badblocks *bb, int prev, in can_combine_front() argument
636 u64 *p = bb->page; in can_combine_front()
651 * The caller of front_combine() will decrease bb->count, therefore
654 static void front_combine(struct badblocks *bb, int prev) in front_combine() argument
656 u64 *p = bb->page; in front_combine()
661 if ((prev + 1) < bb->count) in front_combine()
662 memmove(p + prev, p + prev + 1, (bb->count - prev - 1) * 8); in front_combine()
671 static bool overlap_front(struct badblocks *bb, int front, in overlap_front() argument
674 u64 *p = bb->page; in overlap_front()
686 static bool overlap_behind(struct badblocks *bb, struct badblocks_context *bad, in overlap_behind() argument
689 u64 *p = bb->page; in overlap_behind()
718 static bool can_front_overwrite(struct badblocks *bb, int prev, in can_front_overwrite() argument
721 u64 *p = bb->page; in can_front_overwrite()
724 WARN_ON(!overlap_front(bb, prev, bad)); in can_front_overwrite()
748 if ((bb->count + (*extra)) >= MAX_BADBLOCKS) in can_front_overwrite()
761 static int front_overwrite(struct badblocks *bb, int prev, in front_overwrite() argument
764 u64 *p = bb->page; in front_overwrite()
778 (bb->count - prev - 1) * 8); in front_overwrite()
792 (bb->count - prev - 1) * 8); in front_overwrite()
806 (bb->count - prev - 1) * 8); in front_overwrite()
823 static int insert_at(struct badblocks *bb, int at, struct badblocks_context *bad) in insert_at() argument
825 u64 *p = bb->page; in insert_at()
828 WARN_ON(badblocks_full(bb)); in insert_at()
831 if (at < bb->count) in insert_at()
832 memmove(p + at + 1, p + at, (bb->count - at) * 8); in insert_at()
838 static void badblocks_update_acked(struct badblocks *bb) in badblocks_update_acked() argument
841 u64 *p = bb->page; in badblocks_update_acked()
844 if (!bb->unacked_exist) in badblocks_update_acked()
847 for (i = 0; i < bb->count ; i++) { in badblocks_update_acked()
855 bb->unacked_exist = 0; in badblocks_update_acked()
859 static int _badblocks_set(struct badblocks *bb, sector_t s, int sectors, in _badblocks_set() argument
871 if (bb->shift < 0) in _badblocks_set()
879 if (bb->shift) { in _badblocks_set()
883 rounddown(s, bb->shift); in _badblocks_set()
884 roundup(next, bb->shift); in _badblocks_set()
888 write_seqlock_irqsave(&bb->lock, flags); in _badblocks_set()
893 p = bb->page; in _badblocks_set()
900 if (badblocks_empty(bb)) { in _badblocks_set()
901 len = insert_at(bb, 0, &bad); in _badblocks_set()
902 bb->count++; in _badblocks_set()
907 prev = prev_badblocks(bb, &bad, hint); in _badblocks_set()
911 if (!badblocks_full(bb)) { in _badblocks_set()
915 len = insert_at(bb, 0, &bad); in _badblocks_set()
916 bb->count++; in _badblocks_set()
923 if (overlap_behind(bb, &bad, 0)) { in _badblocks_set()
924 if (can_merge_behind(bb, &bad, 0)) { in _badblocks_set()
925 len = behind_merge(bb, &bad, 0); in _badblocks_set()
940 if (can_combine_front(bb, prev, &bad)) { in _badblocks_set()
941 front_combine(bb, prev); in _badblocks_set()
942 bb->count--; in _badblocks_set()
948 if (overlap_front(bb, prev, &bad)) { in _badblocks_set()
949 if (can_merge_front(bb, prev, &bad)) { in _badblocks_set()
950 len = front_merge(bb, prev, &bad); in _badblocks_set()
955 if (!can_front_overwrite(bb, prev, &bad, &extra)) { in _badblocks_set()
962 len = front_overwrite(bb, prev, &bad, extra); in _badblocks_set()
964 bb->count += extra; in _badblocks_set()
966 if (can_combine_front(bb, prev, &bad)) { in _badblocks_set()
967 front_combine(bb, prev); in _badblocks_set()
968 bb->count--; in _badblocks_set()
975 if (can_merge_front(bb, prev, &bad)) { in _badblocks_set()
976 len = front_merge(bb, prev, &bad); in _badblocks_set()
983 if (badblocks_full(bb)) { in _badblocks_set()
985 if (((prev + 1) < bb->count) && in _badblocks_set()
986 overlap_behind(bb, &bad, prev + 1) && in _badblocks_set()
1001 if ((prev + 1) < bb->count && in _badblocks_set()
1002 overlap_behind(bb, &bad, prev + 1)) in _badblocks_set()
1006 len = insert_at(bb, prev + 1, &bad); in _badblocks_set()
1007 bb->count++; in _badblocks_set()
1026 (prev + 1) < bb->count && in _badblocks_set()
1034 if ((prev + 2) < bb->count) in _badblocks_set()
1036 (bb->count - (prev + 2)) * 8); in _badblocks_set()
1037 bb->count--; in _badblocks_set()
1040 if (space_desired && !badblocks_full(bb)) { in _badblocks_set()
1050 set_changed(bb); in _badblocks_set()
1053 bb->unacked_exist = 1; in _badblocks_set()
1055 badblocks_update_acked(bb); in _badblocks_set()
1058 write_sequnlock_irqrestore(&bb->lock, flags); in _badblocks_set()
1071 * the caller to reduce bb->count.
1073 static int front_clear(struct badblocks *bb, int prev, in front_clear() argument
1078 u64 *p = bb->page; in front_clear()
1091 if ((prev + 1) < bb->count) in front_clear()
1093 (bb->count - prev - 1) * 8); in front_clear()
1116 static int front_splitting_clear(struct badblocks *bb, int prev, in front_splitting_clear() argument
1119 u64 *p = bb->page; in front_splitting_clear()
1128 memmove(p + prev + 2, p + prev + 1, (bb->count - prev - 1) * 8); in front_splitting_clear()
1134 static int _badblocks_clear(struct badblocks *bb, sector_t s, int sectors) in _badblocks_clear() argument
1142 if (bb->shift < 0) in _badblocks_clear()
1150 if (bb->shift) { in _badblocks_clear()
1160 roundup(s, bb->shift); in _badblocks_clear()
1161 rounddown(target, bb->shift); in _badblocks_clear()
1165 write_seqlock_irq(&bb->lock); in _badblocks_clear()
1168 p = bb->page; in _badblocks_clear()
1174 if (badblocks_empty(bb)) { in _badblocks_clear()
1181 prev = prev_badblocks(bb, &bad, hint); in _badblocks_clear()
1185 if (overlap_behind(bb, &bad, 0)) { in _badblocks_clear()
1200 if ((prev + 1) >= bb->count && !overlap_front(bb, prev, &bad)) { in _badblocks_clear()
1207 if (badblocks_full(bb) && (BB_OFFSET(p[prev]) < bad.start) && in _badblocks_clear()
1213 if (overlap_front(bb, prev, &bad)) { in _badblocks_clear()
1217 if ((bb->count + 1) < MAX_BADBLOCKS) { in _badblocks_clear()
1218 len = front_splitting_clear(bb, prev, &bad); in _badblocks_clear()
1219 bb->count += 1; in _badblocks_clear()
1228 len = front_clear(bb, prev, &bad, &deleted); in _badblocks_clear()
1229 bb->count -= deleted; in _badblocks_clear()
1238 if ((prev + 1) < bb->count && overlap_behind(bb, &bad, prev + 1)) { in _badblocks_clear()
1261 badblocks_update_acked(bb); in _badblocks_clear()
1262 set_changed(bb); in _badblocks_clear()
1265 write_sequnlock_irq(&bb->lock); in _badblocks_clear()
1274 static int _badblocks_check(struct badblocks *bb, sector_t s, int sectors, in _badblocks_check() argument
1284 WARN_ON(bb->shift < 0 || sectors == 0); in _badblocks_check()
1286 if (bb->shift > 0) { in _badblocks_check()
1291 rounddown(s, bb->shift); in _badblocks_check()
1292 roundup(target, bb->shift); in _badblocks_check()
1297 seq = read_seqbegin(&bb->lock); in _badblocks_check()
1299 p = bb->page; in _badblocks_check()
1307 if (badblocks_empty(bb)) { in _badblocks_check()
1312 prev = prev_badblocks(bb, &bad, hint); in _badblocks_check()
1316 ((prev + 1) >= bb->count) && !overlap_front(bb, prev, &bad)) { in _badblocks_check()
1322 if ((prev >= 0) && overlap_front(bb, prev, &bad)) { in _badblocks_check()
1342 if ((prev + 1) < bb->count && overlap_behind(bb, &bad, prev + 1)) { in _badblocks_check()
1367 if (read_seqretry(&bb->lock, seq)) in _badblocks_check()
1375 * @bb: the badblocks structure that holds all badblock information
1407 int badblocks_check(struct badblocks *bb, sector_t s, int sectors, in badblocks_check() argument
1410 return _badblocks_check(bb, s, sectors, first_bad, bad_sectors); in badblocks_check()
1416 * @bb: the badblocks structure that holds all badblock information
1429 int badblocks_set(struct badblocks *bb, sector_t s, int sectors, in badblocks_set() argument
1432 return _badblocks_set(bb, s, sectors, acknowledged); in badblocks_set()
1438 * @bb: the badblocks structure that holds all badblock information
1450 int badblocks_clear(struct badblocks *bb, sector_t s, int sectors) in badblocks_clear() argument
1452 return _badblocks_clear(bb, s, sectors); in badblocks_clear()
1458 * @bb: the badblocks structure that holds all badblock information
1463 void ack_all_badblocks(struct badblocks *bb) in ack_all_badblocks() argument
1465 if (bb->page == NULL || bb->changed) in ack_all_badblocks()
1468 write_seqlock_irq(&bb->lock); in ack_all_badblocks()
1470 if (bb->changed == 0 && bb->unacked_exist) { in ack_all_badblocks()
1471 u64 *p = bb->page; in ack_all_badblocks()
1474 for (i = 0; i < bb->count ; i++) { in ack_all_badblocks()
1482 bb->unacked_exist = 0; in ack_all_badblocks()
1484 write_sequnlock_irq(&bb->lock); in ack_all_badblocks()
1490 * @bb: the badblocks structure that holds all badblock information
1497 ssize_t badblocks_show(struct badblocks *bb, char *page, int unack) in badblocks_show() argument
1501 u64 *p = bb->page; in badblocks_show()
1504 if (bb->shift < 0) in badblocks_show()
1508 seq = read_seqbegin(&bb->lock); in badblocks_show()
1513 while (len < PAGE_SIZE && i < bb->count) { in badblocks_show()
1524 (unsigned long long)s << bb->shift, in badblocks_show()
1525 length << bb->shift); in badblocks_show()
1528 bb->unacked_exist = 0; in badblocks_show()
1530 if (read_seqretry(&bb->lock, seq)) in badblocks_show()
1539 * @bb: the badblocks structure that holds all badblock information
1547 ssize_t badblocks_store(struct badblocks *bb, const char *page, size_t len, in badblocks_store() argument
1567 if (badblocks_set(bb, sector, length, !unack)) in badblocks_store()
1574 static int __badblocks_init(struct device *dev, struct badblocks *bb, in __badblocks_init() argument
1577 bb->dev = dev; in __badblocks_init()
1578 bb->count = 0; in __badblocks_init()
1580 bb->shift = 0; in __badblocks_init()
1582 bb->shift = -1; in __badblocks_init()
1584 bb->page = devm_kzalloc(dev, PAGE_SIZE, GFP_KERNEL); in __badblocks_init()
1586 bb->page = kzalloc(PAGE_SIZE, GFP_KERNEL); in __badblocks_init()
1587 if (!bb->page) { in __badblocks_init()
1588 bb->shift = -1; in __badblocks_init()
1591 seqlock_init(&bb->lock); in __badblocks_init()
1598 * @bb: the badblocks structure that holds all badblock information
1605 int badblocks_init(struct badblocks *bb, int enable) in badblocks_init() argument
1607 return __badblocks_init(NULL, bb, enable); in badblocks_init()
1611 int devm_init_badblocks(struct device *dev, struct badblocks *bb) in devm_init_badblocks() argument
1613 if (!bb) in devm_init_badblocks()
1615 return __badblocks_init(dev, bb, 1); in devm_init_badblocks()
1621 * @bb: the badblocks structure that holds all badblock information
1623 void badblocks_exit(struct badblocks *bb) in badblocks_exit() argument
1625 if (!bb) in badblocks_exit()
1627 if (bb->dev) in badblocks_exit()
1628 devm_kfree(bb->dev, bb->page); in badblocks_exit()
1630 kfree(bb->page); in badblocks_exit()
1631 bb->page = NULL; in badblocks_exit()