]> Git Repo - J-linux.git/commitdiff
Merge tag 'printk-for-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek...
authorLinus Torvalds <[email protected]>
Wed, 6 Jun 2018 23:04:55 +0000 (16:04 -0700)
committerLinus Torvalds <[email protected]>
Wed, 6 Jun 2018 23:04:55 +0000 (16:04 -0700)
Pull printk updates from Petr Mladek:

 - Help userspace log daemons to catch up with a flood of messages. They
   will get woken after each message even if the console is far behind
   and handled by another process.

 - Flush printk safe buffers safely even when panic() happens in the
   normal context.

 - Fix possible va_list reuse when race happened in printk_safe().

 - Remove %pCr printf format to prevent sleeping in the atomic context.

 - Misc vsprintf code cleanup.

* tag 'printk-for-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk:
  printk: drop in_nmi check from printk_safe_flush_on_panic()
  lib/vsprintf: Remove atomic-unsafe support for %pCr
  serial: sh-sci: Stop using printk format %pCr
  thermal: bcm2835: Stop using printk format %pCr
  clk: renesas: cpg-mssr: Stop using printk format %pCr
  printk: fix possible reuse of va_list variable
  printk: wake up klogd in vprintk_emit
  vsprintf: Tweak pF/pf comment
  lib/vsprintf: Mark expected switch fall-through
  lib/vsprintf: Replace space with '_' before crng is ready
  lib/vsprintf: Deduplicate pointer_string()
  lib/vsprintf: Move pointer_string() upper
  lib/vsprintf: Make flag_spec global
  lib/vsprintf: Make strspec global
  lib/vsprintf: Make dec_spec global
  lib/test_printf: Mark big constant with UL

1  2 
drivers/clk/renesas/renesas-cpg-mssr.c
drivers/tty/serial/sh-sci.c
kernel/printk/printk.c
lib/vsprintf.c

index 4e88e980fb7697fce7fd4b68d32d78b4c3666ec0,2c9988fef656ffea4d0126dd2c17f5ead8fc1231..69a7c756658b9932e7d4c8a4588f3126c4fbe670
@@@ -258,8 -258,9 +258,9 @@@ struct clk *cpg_mssr_clk_src_twocell_ge
                dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx,
                       PTR_ERR(clk));
        else
-               dev_dbg(dev, "clock (%u, %u) is %pC at %pCr Hz\n",
-                       clkspec->args[0], clkspec->args[1], clk, clk);
+               dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n",
+                       clkspec->args[0], clkspec->args[1], clk,
+                       clk_get_rate(clk));
        return clk;
  }
  
@@@ -326,7 -327,7 +327,7 @@@ static void __init cpg_mssr_register_co
        if (IS_ERR_OR_NULL(clk))
                goto fail;
  
-       dev_dbg(dev, "Core clock %pC at %pCr Hz\n", clk, clk);
+       dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
        priv->clks[id] = clk;
        return;
  
@@@ -392,7 -393,7 +393,7 @@@ static void __init cpg_mssr_register_mo
        if (IS_ERR(clk))
                goto fail;
  
-       dev_dbg(dev, "Module clock %pC at %pCr Hz\n", clk, clk);
+       dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
        priv->clks[id] = clk;
        priv->smstpcr_saved[clock->index / 32].mask |= BIT(clock->index % 32);
        return;
@@@ -693,24 -694,12 +694,24 @@@ static const struct of_device_id cpg_ms
                .data = &r8a7796_cpg_mssr_info,
        },
  #endif
 +#ifdef CONFIG_CLK_R8A77965
 +      {
 +              .compatible = "renesas,r8a77965-cpg-mssr",
 +              .data = &r8a77965_cpg_mssr_info,
 +      },
 +#endif
  #ifdef CONFIG_CLK_R8A77970
        {
                .compatible = "renesas,r8a77970-cpg-mssr",
                .data = &r8a77970_cpg_mssr_info,
        },
  #endif
 +#ifdef CONFIG_CLK_R8A77980
 +      {
 +              .compatible = "renesas,r8a77980-cpg-mssr",
 +              .data = &r8a77980_cpg_mssr_info,
 +      },
 +#endif
  #ifdef CONFIG_CLK_R8A77995
        {
                .compatible = "renesas,r8a77995-cpg-mssr",
index b46b146524ce749591f2a2ba8deda8465aff60ad,a4f82ec665fe79f111a024f141055b3c698102f5..c181eb37f98509e6e2a34a7df62be2e5383d79e3
@@@ -160,7 -160,6 +160,7 @@@ struct sci_port 
  #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
  
  static struct sci_port sci_ports[SCI_NPORTS];
 +static unsigned long sci_ports_in_use;
  static struct uart_driver sci_uart_driver;
  
  static inline struct sci_port *
@@@ -2391,27 -2390,6 +2391,27 @@@ done
  
        uart_update_timeout(port, termios->c_cflag, baud);
  
 +      /* byte size and parity */
 +      switch (termios->c_cflag & CSIZE) {
 +      case CS5:
 +              bits = 7;
 +              break;
 +      case CS6:
 +              bits = 8;
 +              break;
 +      case CS7:
 +              bits = 9;
 +              break;
 +      default:
 +              bits = 10;
 +              break;
 +      }
 +
 +      if (termios->c_cflag & CSTOPB)
 +              bits++;
 +      if (termios->c_cflag & PARENB)
 +              bits++;
 +
        if (best_clk >= 0) {
                if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
                        switch (srr + 1) {
                serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
                serial_port_out(port, SCSMR, smr_val);
                serial_port_out(port, SCBRR, brr);
 -              if (sci_getreg(port, HSSRR)->size)
 -                      serial_port_out(port, HSSRR, srr | HSCIF_SRE);
 +              if (sci_getreg(port, HSSRR)->size) {
 +                      unsigned int hssrr = srr | HSCIF_SRE;
 +                      /* Calculate deviation from intended rate at the
 +                       * center of the last stop bit in sampling clocks.
 +                       */
 +                      int last_stop = bits * 2 - 1;
 +                      int deviation = min_err * srr * last_stop / 2 / baud;
 +
 +                      if (abs(deviation) >= 2) {
 +                              /* At least two sampling clocks off at the
 +                               * last stop bit; we can increase the error
 +                               * margin by shifting the sampling point.
 +                               */
 +                              int shift = min(-8, max(7, deviation / 2));
 +
 +                              hssrr |= (shift << HSCIF_SRHP_SHIFT) &
 +                                       HSCIF_SRHP_MASK;
 +                              hssrr |= HSCIF_SRDE;
 +                      }
 +                      serial_port_out(port, HSSRR, hssrr);
 +              }
  
                /* Wait one bit interval */
                udelay((1000000 + (baud - 1)) / baud);
         * value obtained by this formula is too small. Therefore, if the value
         * is smaller than 20ms, use 20ms as the timeout value for DMA.
         */
 -      /* byte size and parity */
 -      switch (termios->c_cflag & CSIZE) {
 -      case CS5:
 -              bits = 7;
 -              break;
 -      case CS6:
 -              bits = 8;
 -              break;
 -      case CS7:
 -              bits = 9;
 -              break;
 -      default:
 -              bits = 10;
 -              break;
 -      }
 -
 -      if (termios->c_cflag & CSTOPB)
 -              bits++;
 -      if (termios->c_cflag & PARENB)
 -              bits++;
 -
        s->rx_frame = (10000 * bits) / (baud / 100);
  #ifdef CONFIG_SERIAL_SH_SCI_DMA
        s->rx_timeout = s->buf_len_rx * 2 * s->rx_frame;
@@@ -2724,8 -2704,8 +2724,8 @@@ found
                        dev_dbg(dev, "failed to get %s (%ld)\n", clk_names[i],
                                PTR_ERR(clk));
                else
-                       dev_dbg(dev, "clk %s is %pC rate %pCr\n", clk_names[i],
-                               clk, clk);
+                       dev_dbg(dev, "clk %s is %pC rate %lu\n", clk_names[i],
+                               clk, clk_get_rate(clk));
                sci_port->clks[i] = IS_ERR(clk) ? NULL : clk;
        }
        return 0;
@@@ -2910,15 -2890,16 +2910,15 @@@ static void serial_console_write(struc
        unsigned long flags;
        int locked = 1;
  
 -      local_irq_save(flags);
  #if defined(SUPPORT_SYSRQ)
        if (port->sysrq)
                locked = 0;
        else
  #endif
        if (oops_in_progress)
 -              locked = spin_trylock(&port->lock);
 +              locked = spin_trylock_irqsave(&port->lock, flags);
        else
 -              spin_lock(&port->lock);
 +              spin_lock_irqsave(&port->lock, flags);
  
        /* first save SCSCR then disable interrupts, keep clock source */
        ctrl = serial_port_in(port, SCSCR);
        serial_port_out(port, SCSCR, ctrl);
  
        if (locked)
 -              spin_unlock(&port->lock);
 -      local_irq_restore(flags);
 +              spin_unlock_irqrestore(&port->lock, flags);
  }
  
  static int serial_console_setup(struct console *co, char *options)
@@@ -3044,7 -3026,6 +3044,7 @@@ static int sci_remove(struct platform_d
  {
        struct sci_port *port = platform_get_drvdata(dev);
  
 +      sci_ports_in_use &= ~BIT(port->port.line);
        uart_remove_one_port(&sci_uart_driver, &port->port);
  
        sci_cleanup_single(port);
@@@ -3126,8 -3107,6 +3126,8 @@@ static struct plat_sci_port *sci_parse_
  
        /* Get the line number from the aliases node. */
        id = of_alias_get_id(np, "serial");
 +      if (id < 0 && ~sci_ports_in_use)
 +              id = ffz(sci_ports_in_use);
        if (id < 0) {
                dev_err(&pdev->dev, "failed to get alias id (%d)\n", id);
                return NULL;
@@@ -3162,9 -3141,6 +3162,9 @@@ static int sci_probe_single(struct plat
                dev_notice(&dev->dev, "Consider bumping CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
                return -EINVAL;
        }
 +      BUILD_BUG_ON(SCI_NPORTS > sizeof(sci_ports_in_use) * 8);
 +      if (sci_ports_in_use & BIT(index))
 +              return -EBUSY;
  
        mutex_lock(&sci_uart_registration_lock);
        if (!sci_uart_driver.state) {
@@@ -3263,7 -3239,6 +3263,7 @@@ static int sci_probe(struct platform_de
        sh_bios_gdb_detach();
  #endif
  
 +      sci_ports_in_use |= BIT(dev_id);
        return 0;
  }
  
diff --combined kernel/printk/printk.c
index 2f4af216bd6ef97f31b6ffcd0805a85ecfa652ee,fba995b305b104791099cdcff329d35a5b7eab7b..247808333ba430f75c0ac7382bc08d6f219685cf
@@@ -51,7 -51,6 +51,7 @@@
  #include <linux/uaccess.h>
  #include <asm/sections.h>
  
 +#include <trace/events/initcall.h>
  #define CREATE_TRACE_POINTS
  #include <trace/events/printk.h>
  
@@@ -1908,6 -1907,7 +1908,7 @@@ asmlinkage int vprintk_emit(int facilit
                preempt_enable();
        }
  
+       wake_up_klogd();
        return printed_len;
  }
  EXPORT_SYMBOL(vprintk_emit);
@@@ -2289,9 -2289,7 +2290,7 @@@ void console_unlock(void
  {
        static char ext_text[CONSOLE_EXT_LOG_MAX];
        static char text[LOG_LINE_MAX + PREFIX_MAX];
-       static u64 seen_seq;
        unsigned long flags;
-       bool wake_klogd = false;
        bool do_cond_resched, retry;
  
        if (console_suspended) {
@@@ -2335,11 -2333,6 +2334,6 @@@ again
  
                printk_safe_enter_irqsave(flags);
                raw_spin_lock(&logbuf_lock);
-               if (seen_seq != log_next_seq) {
-                       wake_klogd = true;
-                       seen_seq = log_next_seq;
-               }
                if (console_seq < log_first_seq) {
                        len = sprintf(text, "** %u printk messages dropped **\n",
                                      (unsigned)(log_first_seq - console_seq));
@@@ -2397,7 -2390,7 +2391,7 @@@ skip
  
                if (console_lock_spinning_disable_and_check()) {
                        printk_safe_exit_irqrestore(flags);
-                       goto out;
+                       return;
                }
  
                printk_safe_exit_irqrestore(flags);
  
        if (retry && console_trylock())
                goto again;
- out:
-       if (wake_klogd)
-               wake_up_klogd();
  }
  EXPORT_SYMBOL(console_unlock);
  
@@@ -2781,7 -2770,6 +2771,7 @@@ EXPORT_SYMBOL(unregister_console)
   */
  void __init console_init(void)
  {
 +      int ret;
        initcall_t *call;
  
        /* Setup the default TTY line discipline. */
         * inform about problems etc..
         */
        call = __con_initcall_start;
 +      trace_initcall_level("console");
        while (call < __con_initcall_end) {
 -              (*call)();
 +              trace_initcall_start((*call));
 +              ret = (*call)();
 +              trace_initcall_finish((*call), ret);
                call++;
        }
  }
diff --combined lib/vsprintf.c
index 23920c5ff72859c79f4f50e8e267b56c8f230c7c,8999202ad43b0d29ddbb1278d6d45cb2ff1040a5..a48aaa79d352313aa7dda46549f1a3d3e57b0c1f
@@@ -336,7 -336,7 +336,7 @@@ char *put_dec(char *buf, unsigned long 
   *
   * If speed is not important, use snprintf(). It's easy to read the code.
   */
 -int num_to_str(char *buf, int size, unsigned long long num)
 +int num_to_str(char *buf, int size, unsigned long long num, unsigned int width)
  {
        /* put_dec requires 2-byte alignment of the buffer. */
        char tmp[sizeof(num) * 3] __aligned(2);
                len = put_dec(tmp, num) - tmp;
        }
  
 -      if (len > size)
 +      if (len > size || width > size)
                return 0;
 +
 +      if (width > len) {
 +              width = width - len;
 +              for (idx = 0; idx < width; idx++)
 +                      buf[idx] = ' ';
 +      } else {
 +              width = 0;
 +      }
 +
        for (idx = 0; idx < len; ++idx)
 -              buf[idx] = tmp[len - idx - 1];
 -      return len;
 +              buf[idx + width] = tmp[len - idx - 1];
 +
 +      return len + width;
  }
  
  #define SIGN  1               /* unsigned/signed, must be 1 */
@@@ -703,6 -693,22 +703,22 @@@ char *symbol_string(char *buf, char *en
  #endif
  }
  
+ static const struct printf_spec default_str_spec = {
+       .field_width = -1,
+       .precision = -1,
+ };
+ static const struct printf_spec default_flag_spec = {
+       .base = 16,
+       .precision = -1,
+       .flags = SPECIAL | SMALL,
+ };
+ static const struct printf_spec default_dec_spec = {
+       .base = 10,
+       .precision = -1,
+ };
  static noinline_for_stack
  char *resource_string(char *buf, char *end, struct resource *res,
                      struct printf_spec spec, const char *fmt)
                .precision = -1,
                .flags = SMALL | ZEROPAD,
        };
-       static const struct printf_spec dec_spec = {
-               .base = 10,
-               .precision = -1,
-               .flags = 0,
-       };
        static const struct printf_spec str_spec = {
                .field_width = -1,
                .precision = 10,
                .flags = LEFT,
        };
-       static const struct printf_spec flag_spec = {
-               .base = 16,
-               .precision = -1,
-               .flags = SPECIAL | SMALL,
-       };
  
        /* 32-bit res (sizeof==4): 10 chars in dec, 10 in hex ("0x" + 8)
         * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */
                specp = &mem_spec;
        } else if (res->flags & IORESOURCE_IRQ) {
                p = string(p, pend, "irq ", str_spec);
-               specp = &dec_spec;
+               specp = &default_dec_spec;
        } else if (res->flags & IORESOURCE_DMA) {
                p = string(p, pend, "dma ", str_spec);
-               specp = &dec_spec;
+               specp = &default_dec_spec;
        } else if (res->flags & IORESOURCE_BUS) {
                p = string(p, pend, "bus ", str_spec);
                specp = &bus_spec;
                        p = string(p, pend, " disabled", str_spec);
        } else {
                p = string(p, pend, " flags ", str_spec);
-               p = number(p, pend, res->flags, flag_spec);
+               p = number(p, pend, res->flags, default_flag_spec);
        }
        *p++ = ']';
        *p = '\0';
@@@ -913,9 -909,6 +919,6 @@@ char *bitmap_list_string(char *buf, cha
        int cur, rbot, rtop;
        bool first = true;
  
-       /* reused to print numbers */
-       spec = (struct printf_spec){ .base = 10 };
        rbot = cur = find_first_bit(bitmap, nr_bits);
        while (cur < nr_bits) {
                rtop = cur;
                }
                first = false;
  
-               buf = number(buf, end, rbot, spec);
+               buf = number(buf, end, rbot, default_dec_spec);
                if (rbot < rtop) {
                        if (buf < end)
                                *buf = '-';
                        buf++;
  
-                       buf = number(buf, end, rtop, spec);
+                       buf = number(buf, end, rtop, default_dec_spec);
                }
  
                rbot = cur;
@@@ -1354,11 -1347,9 +1357,9 @@@ char *uuid_string(char *buf, char *end
        return string(buf, end, uuid, spec);
  }
  
- int kptr_restrict __read_mostly;
  static noinline_for_stack
- char *restricted_pointer(char *buf, char *end, const void *ptr,
-                        struct printf_spec spec)
+ char *pointer_string(char *buf, char *end, const void *ptr,
+                    struct printf_spec spec)
  {
        spec.base = 16;
        spec.flags |= SMALL;
                spec.flags |= ZEROPAD;
        }
  
+       return number(buf, end, (unsigned long int)ptr, spec);
+ }
+ int kptr_restrict __read_mostly;
+ static noinline_for_stack
+ char *restricted_pointer(char *buf, char *end, const void *ptr,
+                        struct printf_spec spec)
+ {
        switch (kptr_restrict) {
        case 0:
                /* Always print %pK values */
                 * kptr_restrict==1 cannot be used in IRQ context
                 * because its test for CAP_SYSLOG would be meaningless.
                 */
-               if (in_irq() || in_serving_softirq() || in_nmi())
+               if (in_irq() || in_serving_softirq() || in_nmi()) {
+                       if (spec.field_width == -1)
+                               spec.field_width = 2 * sizeof(ptr);
                        return string(buf, end, "pK-error", spec);
+               }
  
                /*
                 * Only print the real pointer value if the current
                break;
        }
  
-       return number(buf, end, (unsigned long)ptr, spec);
+       return pointer_string(buf, end, ptr, spec);
  }
  
  static noinline_for_stack
@@@ -1456,9 -1459,6 +1469,6 @@@ char *clock(char *buf, char *end, struc
                return string(buf, end, NULL, spec);
  
        switch (fmt[1]) {
-       case 'r':
-               return number(buf, end, clk_get_rate(clk), spec);
        case 'n':
        default:
  #ifdef CONFIG_COMMON_CLK
@@@ -1474,23 -1474,13 +1484,13 @@@ char *format_flags(char *buf, char *end
                                        const struct trace_print_flags *names)
  {
        unsigned long mask;
-       const struct printf_spec strspec = {
-               .field_width = -1,
-               .precision = -1,
-       };
-       const struct printf_spec numspec = {
-               .flags = SPECIAL|SMALL,
-               .field_width = -1,
-               .precision = -1,
-               .base = 16,
-       };
  
        for ( ; flags && names->name; names++) {
                mask = names->mask;
                if ((flags & mask) != mask)
                        continue;
  
-               buf = string(buf, end, names->name, strspec);
+               buf = string(buf, end, names->name, default_str_spec);
  
                flags &= ~mask;
                if (flags) {
        }
  
        if (flags)
-               buf = number(buf, end, flags, numspec);
+               buf = number(buf, end, flags, default_flag_spec);
  
        return buf;
  }
@@@ -1548,22 -1538,18 +1548,18 @@@ char *device_node_gen_full_name(const s
  {
        int depth;
        const struct device_node *parent = np->parent;
-       static const struct printf_spec strspec = {
-               .field_width = -1,
-               .precision = -1,
-       };
  
        /* special case for root node */
        if (!parent)
-               return string(buf, end, "/", strspec);
+               return string(buf, end, "/", default_str_spec);
  
        for (depth = 0; parent->parent; depth++)
                parent = parent->parent;
  
        for ( ; depth >= 0; depth--) {
-               buf = string(buf, end, "/", strspec);
+               buf = string(buf, end, "/", default_str_spec);
                buf = string(buf, end, device_node_name_for_depth(np, depth),
-                            strspec);
+                            default_str_spec);
        }
        return buf;
  }
@@@ -1655,36 -1641,19 +1651,22 @@@ char *device_node_string(char *buf, cha
        return widen_string(buf, buf - buf_start, end, spec);
  }
  
- static noinline_for_stack
- char *pointer_string(char *buf, char *end, const void *ptr,
-                    struct printf_spec spec)
- {
-       spec.base = 16;
-       spec.flags |= SMALL;
-       if (spec.field_width == -1) {
-               spec.field_width = 2 * sizeof(ptr);
-               spec.flags |= ZEROPAD;
-       }
-       return number(buf, end, (unsigned long int)ptr, spec);
- }
 -static bool have_filled_random_ptr_key __read_mostly;
 +static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key);
  static siphash_key_t ptr_key __read_mostly;
  
 -static void fill_random_ptr_key(struct random_ready_callback *unused)
 +static void enable_ptr_key_workfn(struct work_struct *work)
  {
        get_random_bytes(&ptr_key, sizeof(ptr_key));
 -      /*
 -       * have_filled_random_ptr_key==true is dependent on get_random_bytes().
 -       * ptr_to_id() needs to see have_filled_random_ptr_key==true
 -       * after get_random_bytes() returns.
 -       */
 -      smp_mb();
 -      WRITE_ONCE(have_filled_random_ptr_key, true);
 +      /* Needs to run from preemptible context */
 +      static_branch_disable(&not_filled_random_ptr_key);
 +}
 +
 +static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn);
 +
 +static void fill_random_ptr_key(struct random_ready_callback *unused)
 +{
 +      /* This may be in an interrupt handler. */
 +      queue_work(system_unbound_wq, &enable_ptr_key_work);
  }
  
  static struct random_ready_callback random_ready = {
@@@ -1698,8 -1667,7 +1680,8 @@@ static int __init initialize_ptr_random
        if (!ret) {
                return 0;
        } else if (ret == -EALREADY) {
 -              fill_random_ptr_key(&random_ready);
 +              /* This is in preemptible context */
 +              enable_ptr_key_workfn(&enable_ptr_key_work);
                return 0;
        }
  
@@@ -1710,13 -1678,13 +1692,13 @@@ early_initcall(initialize_ptr_random)
  /* Maps a pointer to a 32 bit unique identifier. */
  static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec)
  {
+       const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)";
        unsigned long hashval;
-       const int default_width = 2 * sizeof(ptr);
  
 -      if (unlikely(!have_filled_random_ptr_key)) {
 +      if (static_branch_unlikely(&not_filled_random_ptr_key)) {
-               spec.field_width = default_width;
+               spec.field_width = 2 * sizeof(ptr);
                /* string length must be less than default_width */
-               return string(buf, end, "(ptrval)", spec);
+               return string(buf, end, str, spec);
        }
  
  #ifdef CONFIG_64BIT
  #else
        hashval = (unsigned long)siphash_1u32((u32)ptr, &ptr_key);
  #endif
-       spec.flags |= SMALL;
-       if (spec.field_width == -1) {
-               spec.field_width = default_width;
-               spec.flags |= ZEROPAD;
-       }
-       spec.base = 16;
-       return number(buf, end, hashval, spec);
+       return pointer_string(buf, end, (const void *)hashval, spec);
  }
  
  /*
   *
   * Right now we handle:
   *
-  * - 'F' For symbolic function descriptor pointers with offset
-  * - 'f' For simple symbolic function names without offset
-  * - 'S' For symbolic direct pointers with offset
-  * - 's' For symbolic direct pointers without offset
+  * - 'S' For symbolic direct pointers (or function descriptors) with offset
+  * - 's' For symbolic direct pointers (or function descriptors) without offset
+  * - 'F' Same as 'S'
+  * - 'f' Same as 's'
   * - '[FfSs]R' as above with __builtin_extract_return_addr() translation
   * - 'B' For backtraced symbolic direct pointers with offset
   * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
   * ** When making changes please also update:
   *    Documentation/core-api/printk-formats.rst
   *
-  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
-  * function pointers are really function descriptors, which contain a
-  * pointer to the real address.
-  *
   * Note: The default behaviour (unadorned %p) is to hash the address,
   * rendering it useful as a unique identifier.
   */
@@@ -2129,6 -2085,7 +2099,7 @@@ qualifier
  
        case 'x':
                spec->flags |= SMALL;
+               /* fall through */
  
        case 'X':
                spec->base = 16;
@@@ -2605,8 -2562,6 +2576,8 @@@ int vbin_printf(u32 *bin_buf, size_t si
                        case 's':
                        case 'F':
                        case 'f':
 +                      case 'x':
 +                      case 'K':
                                save_arg(void *);
                                break;
                        default:
@@@ -2781,8 -2736,6 +2752,8 @@@ int bstr_printf(char *buf, size_t size
                        case 's':
                        case 'F':
                        case 'f':
 +                      case 'x':
 +                      case 'K':
                                process = true;
                                break;
                        default:
@@@ -3087,8 -3040,10 +3058,10 @@@ int vsscanf(const char *buf, const cha
                        break;
                case 'i':
                        base = 0;
+                       /* fall through */
                case 'd':
                        is_sign = true;
+                       /* fall through */
                case 'u':
                        break;
                case '%':
This page took 0.152058 seconds and 4 git commands to generate.