mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +00:00
printf: Add print format (%pra) for struct range
The use of struct range in the CXL subsystem is growing. In particular, the addition of Dynamic Capacity devices uses struct range in a number of places which are reported in debug and error messages. To wit requiring the printing of the start/end fields in each print became cumbersome. Dan Williams mentions in [1] that it might be time to have a print specifier for struct range similar to struct resource. A few alternatives were considered including '%par', '%r', and '%pn'. %pra follows that struct range is similar to struct resource (%p[rR]) but needs to be different. Based on discussions with Petr and Andy '%pra' was chosen.[2] Andy also suggested to keep the range prints similar to struct resource though combined code. Add hex_range() to handle printing for both pointer types. Finally introduce DEFINE_RANGE() as a parallel to DEFINE_RES_*() and use it in the tests. Cc: Jonathan Corbet <corbet@lwn.net> Cc: linux-doc@vger.kernel.org Cc: open list <linux-kernel@vger.kernel.org> Link: https://lore.kernel.org/all/663922b475e50_d54d72945b@dwillia2-xfh.jf.intel.com.notmuch/ [1] Link: https://lore.kernel.org/all/66cea3bf3332f_f937b29424@iweiny-mobl.notmuch/ [2] Suggested-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Ira Weiny <ira.weiny@intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://patch.msgid.link/20241025-cxl-pra-v2-3-123a825daba2@intel.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
This commit is contained in:
parent
3dff66ff83
commit
4261974701
@ -236,6 +236,19 @@ width of the CPU data path.
|
|||||||
|
|
||||||
Passed by reference.
|
Passed by reference.
|
||||||
|
|
||||||
|
Struct Range
|
||||||
|
------------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
%pra [range 0x0000000060000000-0x000000006fffffff] or
|
||||||
|
[range 0x0000000060000000]
|
||||||
|
|
||||||
|
For printing struct range. struct range holds an arbitrary range of u64
|
||||||
|
values. If start is equal to end only print the start value.
|
||||||
|
|
||||||
|
Passed by reference.
|
||||||
|
|
||||||
DMA address types dma_addr_t
|
DMA address types dma_addr_t
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
@ -31,4 +31,10 @@ int clean_sort_range(struct range *range, int az);
|
|||||||
|
|
||||||
void sort_range(struct range *range, int nr_range);
|
void sort_range(struct range *range, int nr_range);
|
||||||
|
|
||||||
|
#define DEFINE_RANGE(_start, _end) \
|
||||||
|
(struct range) { \
|
||||||
|
.start = (_start), \
|
||||||
|
.end = (_end), \
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -432,6 +432,22 @@ struct_resource(void)
|
|||||||
"%pR", &test_resource);
|
"%pR", &test_resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __init
|
||||||
|
struct_range(void)
|
||||||
|
{
|
||||||
|
struct range test_range = DEFINE_RANGE(0xc0ffee00ba5eba11,
|
||||||
|
0xc0ffee00ba5eba11);
|
||||||
|
test("[range 0xc0ffee00ba5eba11]", "%pra", &test_range);
|
||||||
|
|
||||||
|
test_range = DEFINE_RANGE(0xc0ffee, 0xba5eba11);
|
||||||
|
test("[range 0x0000000000c0ffee-0x00000000ba5eba11]",
|
||||||
|
"%pra", &test_range);
|
||||||
|
|
||||||
|
test_range = DEFINE_RANGE(0xba5eba11, 0xc0ffee);
|
||||||
|
test("[range 0x00000000ba5eba11-0x0000000000c0ffee]",
|
||||||
|
"%pra", &test_range);
|
||||||
|
}
|
||||||
|
|
||||||
static void __init
|
static void __init
|
||||||
addr(void)
|
addr(void)
|
||||||
{
|
{
|
||||||
@ -807,6 +823,7 @@ test_pointer(void)
|
|||||||
symbol_ptr();
|
symbol_ptr();
|
||||||
kernel_ptr();
|
kernel_ptr();
|
||||||
struct_resource();
|
struct_resource();
|
||||||
|
struct_range();
|
||||||
addr();
|
addr();
|
||||||
escaped_str();
|
escaped_str();
|
||||||
hex_string();
|
hex_string();
|
||||||
|
@ -1039,6 +1039,20 @@ static const struct printf_spec default_dec04_spec = {
|
|||||||
.flags = ZEROPAD,
|
.flags = ZEROPAD,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static noinline_for_stack
|
||||||
|
char *hex_range(char *buf, char *end, u64 start_val, u64 end_val,
|
||||||
|
struct printf_spec spec)
|
||||||
|
{
|
||||||
|
buf = number(buf, end, start_val, spec);
|
||||||
|
if (start_val == end_val)
|
||||||
|
return buf;
|
||||||
|
|
||||||
|
if (buf < end)
|
||||||
|
*buf = '-';
|
||||||
|
++buf;
|
||||||
|
return number(buf, end, end_val, spec);
|
||||||
|
}
|
||||||
|
|
||||||
static noinline_for_stack
|
static noinline_for_stack
|
||||||
char *resource_string(char *buf, char *end, struct resource *res,
|
char *resource_string(char *buf, char *end, struct resource *res,
|
||||||
struct printf_spec spec, const char *fmt)
|
struct printf_spec spec, const char *fmt)
|
||||||
@ -1115,11 +1129,7 @@ char *resource_string(char *buf, char *end, struct resource *res,
|
|||||||
p = string_nocheck(p, pend, "size ", str_spec);
|
p = string_nocheck(p, pend, "size ", str_spec);
|
||||||
p = number(p, pend, resource_size(res), *specp);
|
p = number(p, pend, resource_size(res), *specp);
|
||||||
} else {
|
} else {
|
||||||
p = number(p, pend, res->start, *specp);
|
p = hex_range(p, pend, res->start, res->end, *specp);
|
||||||
if (res->start != res->end) {
|
|
||||||
*p++ = '-';
|
|
||||||
p = number(p, pend, res->end, *specp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (decode) {
|
if (decode) {
|
||||||
if (res->flags & IORESOURCE_MEM_64)
|
if (res->flags & IORESOURCE_MEM_64)
|
||||||
@ -1140,6 +1150,31 @@ char *resource_string(char *buf, char *end, struct resource *res,
|
|||||||
return string_nocheck(buf, end, sym, spec);
|
return string_nocheck(buf, end, sym, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static noinline_for_stack
|
||||||
|
char *range_string(char *buf, char *end, const struct range *range,
|
||||||
|
struct printf_spec spec, const char *fmt)
|
||||||
|
{
|
||||||
|
char sym[sizeof("[range 0x0123456789abcdef-0x0123456789abcdef]")];
|
||||||
|
char *p = sym, *pend = sym + sizeof(sym);
|
||||||
|
|
||||||
|
struct printf_spec range_spec = {
|
||||||
|
.field_width = 2 + 2 * sizeof(range->start), /* 0x + 2 * 8 */
|
||||||
|
.flags = SPECIAL | SMALL | ZEROPAD,
|
||||||
|
.base = 16,
|
||||||
|
.precision = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (check_pointer(&buf, end, range, spec))
|
||||||
|
return buf;
|
||||||
|
|
||||||
|
p = string_nocheck(p, pend, "[range ", default_str_spec);
|
||||||
|
p = hex_range(p, pend, range->start, range->end, range_spec);
|
||||||
|
*p++ = ']';
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
return string_nocheck(buf, end, sym, spec);
|
||||||
|
}
|
||||||
|
|
||||||
static noinline_for_stack
|
static noinline_for_stack
|
||||||
char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
|
char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
|
||||||
const char *fmt)
|
const char *fmt)
|
||||||
@ -2229,6 +2264,15 @@ char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode,
|
|||||||
return widen_string(buf, buf - buf_start, end, spec);
|
return widen_string(buf, buf - buf_start, end, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static noinline_for_stack
|
||||||
|
char *resource_or_range(const char *fmt, char *buf, char *end, void *ptr,
|
||||||
|
struct printf_spec spec)
|
||||||
|
{
|
||||||
|
if (*fmt == 'r' && fmt[1] == 'a')
|
||||||
|
return range_string(buf, end, ptr, spec, fmt);
|
||||||
|
return resource_string(buf, end, ptr, spec, fmt);
|
||||||
|
}
|
||||||
|
|
||||||
int __init no_hash_pointers_enable(char *str)
|
int __init no_hash_pointers_enable(char *str)
|
||||||
{
|
{
|
||||||
if (no_hash_pointers)
|
if (no_hash_pointers)
|
||||||
@ -2277,6 +2321,7 @@ char *rust_fmt_argument(char *buf, char *end, void *ptr);
|
|||||||
* - 'Bb' as above with module build ID (for use in backtraces)
|
* - 'Bb' as above with module build ID (for use in backtraces)
|
||||||
* - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
|
* - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
|
||||||
* - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201]
|
* - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201]
|
||||||
|
* - 'ra' For struct ranges, e.g., [range 0x0000000000000000 - 0x00000000000000ff]
|
||||||
* - 'b[l]' For a bitmap, the number of bits is determined by the field
|
* - 'b[l]' For a bitmap, the number of bits is determined by the field
|
||||||
* width which must be explicitly specified either as part of the
|
* width which must be explicitly specified either as part of the
|
||||||
* format string '%32b[l]' or through '%*b[l]', [l] selects
|
* format string '%32b[l]' or through '%*b[l]', [l] selects
|
||||||
@ -2401,7 +2446,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
|
|||||||
return symbol_string(buf, end, ptr, spec, fmt);
|
return symbol_string(buf, end, ptr, spec, fmt);
|
||||||
case 'R':
|
case 'R':
|
||||||
case 'r':
|
case 'r':
|
||||||
return resource_string(buf, end, ptr, spec, fmt);
|
return resource_or_range(fmt, buf, end, ptr, spec);
|
||||||
case 'h':
|
case 'h':
|
||||||
return hex_string(buf, end, ptr, spec, fmt);
|
return hex_string(buf, end, ptr, spec, fmt);
|
||||||
case 'b':
|
case 'b':
|
||||||
|
Loading…
Reference in New Issue
Block a user