fiq_printk.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * arch/arm/kernel/fiq_printk.c
  3. *
  4. * Copyright (C) 2011-2012 Amlogic, Inc.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  14. * more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. #include <linux/kernel.h>
  21. #include <linux/mm.h>
  22. #include <linux/tty.h>
  23. #include <linux/tty_driver.h>
  24. #include <linux/console.h>
  25. #include <linux/init.h>
  26. #include <linux/jiffies.h>
  27. #include <linux/nmi.h>
  28. #include <linux/module.h>
  29. #include <linux/moduleparam.h>
  30. #include <linux/interrupt.h>
  31. #include <linux/delay.h>
  32. #include <linux/smp.h>
  33. #include <linux/security.h>
  34. #include <linux/bootmem.h>
  35. #include <linux/syscalls.h>
  36. #include <linux/kexec.h>
  37. #include <linux/ratelimit.h>
  38. #include <linux/kmsg_dump.h>
  39. #include <linux/syslog.h>
  40. #include <linux/timer.h>
  41. #include <asm/uaccess.h>
  42. #define MAX_PRINT_SIZE 1024
  43. #define FIQ_PREF "<FIQ>:"
  44. static unsigned char fiqprint_buf[MAX_PRINT_SIZE+4];
  45. static unsigned char fiqprint_buf1[MAX_PRINT_SIZE+4];
  46. static int fiqprint_buf_off=0;
  47. static struct timer_list fiq_print_timer;
  48. /* Must call in FIQ mode */
  49. int fiq_vprintk(const char *fmt, va_list args)
  50. {
  51. int r;
  52. char *bufptr = fiqprint_buf + fiqprint_buf_off;
  53. int buflen = MAX_PRINT_SIZE - fiqprint_buf_off;
  54. if (buflen > sizeof(FIQ_PREF) + 16) {
  55. strcpy(bufptr, FIQ_PREF);
  56. bufptr += strlen(FIQ_PREF);
  57. buflen -= strlen(FIQ_PREF);
  58. }
  59. r = vscnprintf(bufptr, MAX_PRINT_SIZE - fiqprint_buf_off, fmt, args);
  60. fiqprint_buf_off += r;
  61. if (fiqprint_buf_off > MAX_PRINT_SIZE)
  62. fiqprint_buf_off = 0; // Overflow, drop all
  63. return r;
  64. }
  65. EXPORT_SYMBOL(fiq_vprintk);
  66. int fiq_printk(const char *fmt, ...)
  67. {
  68. int r;
  69. va_list args;
  70. va_start(args, fmt);
  71. r = fiq_vprintk(fmt, args);
  72. va_end(args);
  73. return r;
  74. }
  75. EXPORT_SYMBOL(fiq_printk);
  76. static void fiq_printk_timer(unsigned long arg)
  77. {
  78. unsigned long flags;
  79. int len = 0;
  80. if (fiqprint_buf_off > 0) {
  81. raw_local_save_flags(flags);
  82. local_fiq_disable();
  83. memcpy(fiqprint_buf1, fiqprint_buf, fiqprint_buf_off);
  84. len = fiqprint_buf_off;
  85. fiqprint_buf_off = 0;
  86. fiqprint_buf1[len] = '\n';
  87. fiqprint_buf1[len + 1] = '0';
  88. raw_local_irq_restore(flags);
  89. }
  90. if (len > 0)
  91. printk("%s\n", fiqprint_buf1);
  92. mod_timer(&fiq_print_timer,jiffies + HZ / 10);
  93. }
  94. static __init int fiq_printk_init(void)
  95. {
  96. init_timer(&fiq_print_timer);
  97. fiq_print_timer.function = fiq_printk_timer;
  98. fiq_print_timer.expires = jiffies + 1;
  99. fiq_print_timer.data = 0;
  100. add_timer(&fiq_print_timer);
  101. return 0;
  102. }
  103. module_init(fiq_printk_init);