diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Kconfig.debug | 38 | ||||
| -rw-r--r-- | lib/Kconfig.kgdb | 3 | ||||
| -rw-r--r-- | lib/Makefile | 2 | ||||
| -rw-r--r-- | lib/bcd.c | 14 | ||||
| -rw-r--r-- | lib/cpumask.c | 9 | ||||
| -rw-r--r-- | lib/debugobjects.c | 4 | ||||
| -rw-r--r-- | lib/scatterlist.c | 176 | ||||
| -rw-r--r-- | lib/smp_processor_id.c | 6 |
8 files changed, 195 insertions, 57 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ba106db5a65b..e1d4764435ed 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
| @@ -150,7 +150,7 @@ config DETECT_SOFTLOCKUP | |||
| 150 | help | 150 | help |
| 151 | Say Y here to enable the kernel to detect "soft lockups", | 151 | Say Y here to enable the kernel to detect "soft lockups", |
| 152 | which are bugs that cause the kernel to loop in kernel | 152 | which are bugs that cause the kernel to loop in kernel |
| 153 | mode for more than 10 seconds, without giving other tasks a | 153 | mode for more than 60 seconds, without giving other tasks a |
| 154 | chance to run. | 154 | chance to run. |
| 155 | 155 | ||
| 156 | When a soft-lockup is detected, the kernel will print the | 156 | When a soft-lockup is detected, the kernel will print the |
| @@ -162,6 +162,30 @@ config DETECT_SOFTLOCKUP | |||
| 162 | can be detected via the NMI-watchdog, on platforms that | 162 | can be detected via the NMI-watchdog, on platforms that |
| 163 | support it.) | 163 | support it.) |
| 164 | 164 | ||
| 165 | config BOOTPARAM_SOFTLOCKUP_PANIC | ||
| 166 | bool "Panic (Reboot) On Soft Lockups" | ||
| 167 | depends on DETECT_SOFTLOCKUP | ||
| 168 | help | ||
| 169 | Say Y here to enable the kernel to panic on "soft lockups", | ||
| 170 | which are bugs that cause the kernel to loop in kernel | ||
| 171 | mode for more than 60 seconds, without giving other tasks a | ||
| 172 | chance to run. | ||
| 173 | |||
| 174 | The panic can be used in combination with panic_timeout, | ||
| 175 | to cause the system to reboot automatically after a | ||
| 176 | lockup has been detected. This feature is useful for | ||
| 177 | high-availability systems that have uptime guarantees and | ||
| 178 | where a lockup must be resolved ASAP. | ||
| 179 | |||
| 180 | Say N if unsure. | ||
| 181 | |||
| 182 | config BOOTPARAM_SOFTLOCKUP_PANIC_VALUE | ||
| 183 | int | ||
| 184 | depends on DETECT_SOFTLOCKUP | ||
| 185 | range 0 1 | ||
| 186 | default 0 if !BOOTPARAM_SOFTLOCKUP_PANIC | ||
| 187 | default 1 if BOOTPARAM_SOFTLOCKUP_PANIC | ||
| 188 | |||
| 165 | config SCHED_DEBUG | 189 | config SCHED_DEBUG |
| 166 | bool "Collect scheduler debugging info" | 190 | bool "Collect scheduler debugging info" |
| 167 | depends on DEBUG_KERNEL && PROC_FS | 191 | depends on DEBUG_KERNEL && PROC_FS |
| @@ -481,6 +505,18 @@ config DEBUG_WRITECOUNT | |||
| 481 | 505 | ||
| 482 | If unsure, say N. | 506 | If unsure, say N. |
| 483 | 507 | ||
| 508 | config DEBUG_MEMORY_INIT | ||
| 509 | bool "Debug memory initialisation" if EMBEDDED | ||
| 510 | default !EMBEDDED | ||
| 511 | help | ||
| 512 | Enable this for additional checks during memory initialisation. | ||
| 513 | The sanity checks verify aspects of the VM such as the memory model | ||
| 514 | and other information provided by the architecture. Verbose | ||
| 515 | information will be printed at KERN_DEBUG loglevel depending | ||
| 516 | on the mminit_loglevel= command-line option. | ||
| 517 | |||
| 518 | If unsure, say Y | ||
| 519 | |||
| 484 | config DEBUG_LIST | 520 | config DEBUG_LIST |
| 485 | bool "Debug linked list manipulation" | 521 | bool "Debug linked list manipulation" |
| 486 | depends on DEBUG_KERNEL | 522 | depends on DEBUG_KERNEL |
diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb index a5d4b1dac2a5..2cfd2721f7ed 100644 --- a/lib/Kconfig.kgdb +++ b/lib/Kconfig.kgdb | |||
| @@ -1,7 +1,4 @@ | |||
| 1 | 1 | ||
| 2 | config HAVE_ARCH_KGDB_SHADOW_INFO | ||
| 3 | bool | ||
| 4 | |||
| 5 | config HAVE_ARCH_KGDB | 2 | config HAVE_ARCH_KGDB |
| 6 | bool | 3 | bool |
| 7 | 4 | ||
diff --git a/lib/Makefile b/lib/Makefile index 818c4d455518..9085ad6fa53d 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
| @@ -18,7 +18,7 @@ lib-$(CONFIG_SMP) += cpumask.o | |||
| 18 | 18 | ||
| 19 | lib-y += kobject.o kref.o klist.o | 19 | lib-y += kobject.o kref.o klist.o |
| 20 | 20 | ||
| 21 | obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ | 21 | obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ |
| 22 | bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o | 22 | bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o |
| 23 | 23 | ||
| 24 | ifeq ($(CONFIG_DEBUG_KOBJECT),y) | 24 | ifeq ($(CONFIG_DEBUG_KOBJECT),y) |
diff --git a/lib/bcd.c b/lib/bcd.c new file mode 100644 index 000000000000..d74257fd0fe7 --- /dev/null +++ b/lib/bcd.c | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | #include <linux/bcd.h> | ||
| 2 | #include <linux/module.h> | ||
| 3 | |||
| 4 | unsigned bcd2bin(unsigned char val) | ||
| 5 | { | ||
| 6 | return (val & 0x0f) + (val >> 4) * 10; | ||
| 7 | } | ||
| 8 | EXPORT_SYMBOL(bcd2bin); | ||
| 9 | |||
| 10 | unsigned char bin2bcd(unsigned val) | ||
| 11 | { | ||
| 12 | return ((val / 10) << 4) + val % 10; | ||
| 13 | } | ||
| 14 | EXPORT_SYMBOL(bin2bcd); | ||
diff --git a/lib/cpumask.c b/lib/cpumask.c index bb4f76d3c3e7..5f97dc25ef9c 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c | |||
| @@ -15,6 +15,15 @@ int __next_cpu(int n, const cpumask_t *srcp) | |||
| 15 | } | 15 | } |
| 16 | EXPORT_SYMBOL(__next_cpu); | 16 | EXPORT_SYMBOL(__next_cpu); |
| 17 | 17 | ||
| 18 | #if NR_CPUS > 64 | ||
| 19 | int __next_cpu_nr(int n, const cpumask_t *srcp) | ||
| 20 | { | ||
| 21 | return min_t(int, nr_cpu_ids, | ||
| 22 | find_next_bit(srcp->bits, nr_cpu_ids, n+1)); | ||
| 23 | } | ||
| 24 | EXPORT_SYMBOL(__next_cpu_nr); | ||
| 25 | #endif | ||
| 26 | |||
| 18 | int __any_online_cpu(const cpumask_t *mask) | 27 | int __any_online_cpu(const cpumask_t *mask) |
| 19 | { | 28 | { |
| 20 | int cpu; | 29 | int cpu; |
diff --git a/lib/debugobjects.c b/lib/debugobjects.c index 85b18d79be89..f86196390cfd 100644 --- a/lib/debugobjects.c +++ b/lib/debugobjects.c | |||
| @@ -226,15 +226,13 @@ debug_object_fixup(int (*fixup)(void *addr, enum debug_obj_state state), | |||
| 226 | 226 | ||
| 227 | static void debug_object_is_on_stack(void *addr, int onstack) | 227 | static void debug_object_is_on_stack(void *addr, int onstack) |
| 228 | { | 228 | { |
| 229 | void *stack = current->stack; | ||
| 230 | int is_on_stack; | 229 | int is_on_stack; |
| 231 | static int limit; | 230 | static int limit; |
| 232 | 231 | ||
| 233 | if (limit > 4) | 232 | if (limit > 4) |
| 234 | return; | 233 | return; |
| 235 | 234 | ||
| 236 | is_on_stack = (addr >= stack && addr < (stack + THREAD_SIZE)); | 235 | is_on_stack = object_is_on_stack(addr); |
| 237 | |||
| 238 | if (is_on_stack == onstack) | 236 | if (is_on_stack == onstack) |
| 239 | return; | 237 | return; |
| 240 | 238 | ||
diff --git a/lib/scatterlist.c b/lib/scatterlist.c index b80c21100d78..876ba6d5b670 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c | |||
| @@ -295,6 +295,117 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask) | |||
| 295 | EXPORT_SYMBOL(sg_alloc_table); | 295 | EXPORT_SYMBOL(sg_alloc_table); |
| 296 | 296 | ||
| 297 | /** | 297 | /** |
| 298 | * sg_miter_start - start mapping iteration over a sg list | ||
| 299 | * @miter: sg mapping iter to be started | ||
| 300 | * @sgl: sg list to iterate over | ||
| 301 | * @nents: number of sg entries | ||
| 302 | * | ||
| 303 | * Description: | ||
| 304 | * Starts mapping iterator @miter. | ||
| 305 | * | ||
| 306 | * Context: | ||
| 307 | * Don't care. | ||
| 308 | */ | ||
| 309 | void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl, | ||
| 310 | unsigned int nents, unsigned int flags) | ||
| 311 | { | ||
| 312 | memset(miter, 0, sizeof(struct sg_mapping_iter)); | ||
| 313 | |||
| 314 | miter->__sg = sgl; | ||
| 315 | miter->__nents = nents; | ||
| 316 | miter->__offset = 0; | ||
| 317 | miter->__flags = flags; | ||
| 318 | } | ||
| 319 | EXPORT_SYMBOL(sg_miter_start); | ||
| 320 | |||
| 321 | /** | ||
| 322 | * sg_miter_next - proceed mapping iterator to the next mapping | ||
| 323 | * @miter: sg mapping iter to proceed | ||
| 324 | * | ||
| 325 | * Description: | ||
| 326 | * Proceeds @miter@ to the next mapping. @miter@ should have been | ||
| 327 | * started using sg_miter_start(). On successful return, | ||
| 328 | * @miter@->page, @miter@->addr and @miter@->length point to the | ||
| 329 | * current mapping. | ||
| 330 | * | ||
| 331 | * Context: | ||
| 332 | * IRQ disabled if SG_MITER_ATOMIC. IRQ must stay disabled till | ||
| 333 | * @miter@ is stopped. May sleep if !SG_MITER_ATOMIC. | ||
| 334 | * | ||
| 335 | * Returns: | ||
| 336 | * true if @miter contains the next mapping. false if end of sg | ||
| 337 | * list is reached. | ||
| 338 | */ | ||
| 339 | bool sg_miter_next(struct sg_mapping_iter *miter) | ||
| 340 | { | ||
| 341 | unsigned int off, len; | ||
| 342 | |||
| 343 | /* check for end and drop resources from the last iteration */ | ||
| 344 | if (!miter->__nents) | ||
| 345 | return false; | ||
| 346 | |||
| 347 | sg_miter_stop(miter); | ||
| 348 | |||
| 349 | /* get to the next sg if necessary. __offset is adjusted by stop */ | ||
| 350 | if (miter->__offset == miter->__sg->length && --miter->__nents) { | ||
| 351 | miter->__sg = sg_next(miter->__sg); | ||
| 352 | miter->__offset = 0; | ||
| 353 | } | ||
| 354 | |||
| 355 | /* map the next page */ | ||
| 356 | off = miter->__sg->offset + miter->__offset; | ||
| 357 | len = miter->__sg->length - miter->__offset; | ||
| 358 | |||
| 359 | miter->page = nth_page(sg_page(miter->__sg), off >> PAGE_SHIFT); | ||
| 360 | off &= ~PAGE_MASK; | ||
| 361 | miter->length = min_t(unsigned int, len, PAGE_SIZE - off); | ||
| 362 | miter->consumed = miter->length; | ||
| 363 | |||
| 364 | if (miter->__flags & SG_MITER_ATOMIC) | ||
| 365 | miter->addr = kmap_atomic(miter->page, KM_BIO_SRC_IRQ) + off; | ||
| 366 | else | ||
| 367 | miter->addr = kmap(miter->page) + off; | ||
| 368 | |||
| 369 | return true; | ||
| 370 | } | ||
| 371 | EXPORT_SYMBOL(sg_miter_next); | ||
| 372 | |||
| 373 | /** | ||
| 374 | * sg_miter_stop - stop mapping iteration | ||
| 375 | * @miter: sg mapping iter to be stopped | ||
| 376 | * | ||
| 377 | * Description: | ||
| 378 | * Stops mapping iterator @miter. @miter should have been started | ||
| 379 | * started using sg_miter_start(). A stopped iteration can be | ||
| 380 | * resumed by calling sg_miter_next() on it. This is useful when | ||
| 381 | * resources (kmap) need to be released during iteration. | ||
| 382 | * | ||
| 383 | * Context: | ||
| 384 | * IRQ disabled if the SG_MITER_ATOMIC is set. Don't care otherwise. | ||
| 385 | */ | ||
| 386 | void sg_miter_stop(struct sg_mapping_iter *miter) | ||
| 387 | { | ||
| 388 | WARN_ON(miter->consumed > miter->length); | ||
| 389 | |||
| 390 | /* drop resources from the last iteration */ | ||
| 391 | if (miter->addr) { | ||
| 392 | miter->__offset += miter->consumed; | ||
| 393 | |||
| 394 | if (miter->__flags & SG_MITER_ATOMIC) { | ||
| 395 | WARN_ON(!irqs_disabled()); | ||
| 396 | kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ); | ||
| 397 | } else | ||
| 398 | kunmap(miter->addr); | ||
| 399 | |||
| 400 | miter->page = NULL; | ||
| 401 | miter->addr = NULL; | ||
| 402 | miter->length = 0; | ||
| 403 | miter->consumed = 0; | ||
| 404 | } | ||
| 405 | } | ||
| 406 | EXPORT_SYMBOL(sg_miter_stop); | ||
| 407 | |||
| 408 | /** | ||
| 298 | * sg_copy_buffer - Copy data between a linear buffer and an SG list | 409 | * sg_copy_buffer - Copy data between a linear buffer and an SG list |
| 299 | * @sgl: The SG list | 410 | * @sgl: The SG list |
| 300 | * @nents: Number of SG entries | 411 | * @nents: Number of SG entries |
| @@ -309,56 +420,29 @@ EXPORT_SYMBOL(sg_alloc_table); | |||
| 309 | static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, | 420 | static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, |
| 310 | void *buf, size_t buflen, int to_buffer) | 421 | void *buf, size_t buflen, int to_buffer) |
| 311 | { | 422 | { |
| 312 | struct scatterlist *sg; | 423 | unsigned int offset = 0; |
| 313 | size_t buf_off = 0; | 424 | struct sg_mapping_iter miter; |
| 314 | int i; | 425 | |
| 315 | 426 | sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC); | |
| 316 | WARN_ON(!irqs_disabled()); | 427 | |
| 317 | 428 | while (sg_miter_next(&miter) && offset < buflen) { | |
| 318 | for_each_sg(sgl, sg, nents, i) { | 429 | unsigned int len; |
| 319 | struct page *page; | 430 | |
| 320 | int n = 0; | 431 | len = min(miter.length, buflen - offset); |
| 321 | unsigned int sg_off = sg->offset; | 432 | |
| 322 | unsigned int sg_copy = sg->length; | 433 | if (to_buffer) |
| 323 | 434 | memcpy(buf + offset, miter.addr, len); | |
| 324 | if (sg_copy > buflen) | 435 | else { |
| 325 | sg_copy = buflen; | 436 | memcpy(miter.addr, buf + offset, len); |
| 326 | buflen -= sg_copy; | 437 | flush_kernel_dcache_page(miter.page); |
| 327 | |||
| 328 | while (sg_copy > 0) { | ||
| 329 | unsigned int page_copy; | ||
| 330 | void *p; | ||
| 331 | |||
| 332 | page_copy = PAGE_SIZE - sg_off; | ||
| 333 | if (page_copy > sg_copy) | ||
| 334 | page_copy = sg_copy; | ||
| 335 | |||
| 336 | page = nth_page(sg_page(sg), n); | ||
| 337 | p = kmap_atomic(page, KM_BIO_SRC_IRQ); | ||
| 338 | |||
| 339 | if (to_buffer) | ||
| 340 | memcpy(buf + buf_off, p + sg_off, page_copy); | ||
| 341 | else { | ||
| 342 | memcpy(p + sg_off, buf + buf_off, page_copy); | ||
| 343 | flush_kernel_dcache_page(page); | ||
| 344 | } | ||
| 345 | |||
| 346 | kunmap_atomic(p, KM_BIO_SRC_IRQ); | ||
| 347 | |||
| 348 | buf_off += page_copy; | ||
| 349 | sg_off += page_copy; | ||
| 350 | if (sg_off == PAGE_SIZE) { | ||
| 351 | sg_off = 0; | ||
| 352 | n++; | ||
| 353 | } | ||
| 354 | sg_copy -= page_copy; | ||
| 355 | } | 438 | } |
| 356 | 439 | ||
| 357 | if (!buflen) | 440 | offset += len; |
| 358 | break; | ||
| 359 | } | 441 | } |
| 360 | 442 | ||
| 361 | return buf_off; | 443 | sg_miter_stop(&miter); |
| 444 | |||
| 445 | return offset; | ||
| 362 | } | 446 | } |
| 363 | 447 | ||
| 364 | /** | 448 | /** |
diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c index 3b4dc098181e..c4381d9516f6 100644 --- a/lib/smp_processor_id.c +++ b/lib/smp_processor_id.c | |||
| @@ -11,7 +11,7 @@ notrace unsigned int debug_smp_processor_id(void) | |||
| 11 | { | 11 | { |
| 12 | unsigned long preempt_count = preempt_count(); | 12 | unsigned long preempt_count = preempt_count(); |
| 13 | int this_cpu = raw_smp_processor_id(); | 13 | int this_cpu = raw_smp_processor_id(); |
| 14 | cpumask_t this_mask; | 14 | cpumask_of_cpu_ptr_declare(this_mask); |
| 15 | 15 | ||
| 16 | if (likely(preempt_count)) | 16 | if (likely(preempt_count)) |
| 17 | goto out; | 17 | goto out; |
| @@ -23,9 +23,9 @@ notrace unsigned int debug_smp_processor_id(void) | |||
| 23 | * Kernel threads bound to a single CPU can safely use | 23 | * Kernel threads bound to a single CPU can safely use |
| 24 | * smp_processor_id(): | 24 | * smp_processor_id(): |
| 25 | */ | 25 | */ |
| 26 | this_mask = cpumask_of_cpu(this_cpu); | 26 | cpumask_of_cpu_ptr_next(this_mask, this_cpu); |
| 27 | 27 | ||
| 28 | if (cpus_equal(current->cpus_allowed, this_mask)) | 28 | if (cpus_equal(current->cpus_allowed, *this_mask)) |
| 29 | goto out; | 29 | goto out; |
| 30 | 30 | ||
| 31 | /* | 31 | /* |
