summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Jiang <dave.jiang@intel.com>2024-10-28 14:46:17 -0700
committerDave Jiang <dave.jiang@intel.com>2024-10-28 14:46:17 -0700
commit86bcd81d66d63c549e98c9c502ccd3be01a52fe2 (patch)
tree2b52d5120714d9856439db66ad3a91ce413f7c25
parent9474d586819940f00a98dd98015fe456f9b35452 (diff)
parentbdd7c35fc59f391de5a1d93ca7cbc715bf8c015c (diff)
Merge branch 'cxl/for-6.12/printf' into cxl-for-next
Add support for adding a printf specifier '$pra' to emit 'struct range' content.
-rw-r--r--Documentation/core-api/printk-formats.rst20
-rw-r--r--drivers/cxl/core/cdat.c8
-rw-r--r--include/linux/range.h6
-rw-r--r--lib/test_printf.c61
-rw-r--r--lib/vsprintf.c57
5 files changed, 141 insertions, 11 deletions
diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
index 14e093da3ccd..ecccc0473da9 100644
--- a/Documentation/core-api/printk-formats.rst
+++ b/Documentation/core-api/printk-formats.rst
@@ -209,12 +209,17 @@ Struct Resources
::
%pr [mem 0x60000000-0x6fffffff flags 0x2200] or
+ [mem 0x60000000 flags 0x2200] or
[mem 0x0000000060000000-0x000000006fffffff flags 0x2200]
+ [mem 0x0000000060000000 flags 0x2200]
%pR [mem 0x60000000-0x6fffffff pref] or
+ [mem 0x60000000 pref] or
[mem 0x0000000060000000-0x000000006fffffff pref]
+ [mem 0x0000000060000000 pref]
For printing struct resources. The ``R`` and ``r`` specifiers result in a
-printed resource with (R) or without (r) a decoded flags member.
+printed resource with (R) or without (r) a decoded flags member. If start is
+equal to end only print the start value.
Passed by reference.
@@ -231,6 +236,19 @@ width of the CPU data path.
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
----------------------------
diff --git a/drivers/cxl/core/cdat.c b/drivers/cxl/core/cdat.c
index ef1621d40f05..438869df241a 100644
--- a/drivers/cxl/core/cdat.c
+++ b/drivers/cxl/core/cdat.c
@@ -247,8 +247,8 @@ static void update_perf_entry(struct device *dev, struct dsmas_entry *dent,
dpa_perf->dpa_range = dent->dpa_range;
dpa_perf->qos_class = dent->qos_class;
dev_dbg(dev,
- "DSMAS: dpa: %#llx qos: %d read_bw: %d write_bw %d read_lat: %d write_lat: %d\n",
- dent->dpa_range.start, dpa_perf->qos_class,
+ "DSMAS: dpa: %pra qos: %d read_bw: %d write_bw %d read_lat: %d write_lat: %d\n",
+ &dent->dpa_range, dpa_perf->qos_class,
dent->coord[ACCESS_COORDINATE_CPU].read_bandwidth,
dent->coord[ACCESS_COORDINATE_CPU].write_bandwidth,
dent->coord[ACCESS_COORDINATE_CPU].read_latency,
@@ -279,8 +279,8 @@ static void cxl_memdev_set_qos_class(struct cxl_dev_state *cxlds,
range_contains(&pmem_range, &dent->dpa_range))
update_perf_entry(dev, dent, &mds->pmem_perf);
else
- dev_dbg(dev, "no partition for dsmas dpa: %#llx\n",
- dent->dpa_range.start);
+ dev_dbg(dev, "no partition for dsmas dpa: %pra\n",
+ &dent->dpa_range);
}
}
diff --git a/include/linux/range.h b/include/linux/range.h
index 7dc5e835e079..732c7fdbfd30 100644
--- a/include/linux/range.h
+++ b/include/linux/range.h
@@ -32,4 +32,10 @@ int clean_sort_range(struct range *range, int az);
void sort_range(struct range *range, int nr_range);
+#define DEFINE_RANGE(_start, _end) \
+(struct range) { \
+ .start = (_start), \
+ .end = (_end), \
+ }
+
#endif
diff --git a/lib/test_printf.c b/lib/test_printf.c
index 8448b6d02bd9..59dbe4f9a4cb 100644
--- a/lib/test_printf.c
+++ b/lib/test_printf.c
@@ -386,6 +386,66 @@ kernel_ptr(void)
static void __init
struct_resource(void)
{
+ struct resource test_resource = {
+ .start = 0xc0ffee00,
+ .end = 0xc0ffee00,
+ .flags = IORESOURCE_MEM,
+ };
+
+ test("[mem 0xc0ffee00 flags 0x200]",
+ "%pr", &test_resource);
+
+ test_resource = (struct resource) {
+ .start = 0xc0ffee,
+ .end = 0xba5eba11,
+ .flags = IORESOURCE_MEM,
+ };
+ test("[mem 0x00c0ffee-0xba5eba11 flags 0x200]",
+ "%pr", &test_resource);
+
+ test_resource = (struct resource) {
+ .start = 0xba5eba11,
+ .end = 0xc0ffee,
+ .flags = IORESOURCE_MEM,
+ };
+ test("[mem 0xba5eba11-0x00c0ffee flags 0x200]",
+ "%pr", &test_resource);
+
+ test_resource = (struct resource) {
+ .start = 0xba5eba11,
+ .end = 0xba5eca11,
+ .flags = IORESOURCE_MEM,
+ };
+
+ test("[mem 0xba5eba11-0xba5eca11 flags 0x200]",
+ "%pr", &test_resource);
+
+ test_resource = (struct resource) {
+ .start = 0xba11,
+ .end = 0xca10,
+ .flags = IORESOURCE_IO |
+ IORESOURCE_DISABLED |
+ IORESOURCE_UNSET,
+ };
+
+ test("[io size 0x1000 disabled]",
+ "%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
@@ -763,6 +823,7 @@ test_pointer(void)
symbol_ptr();
kernel_ptr();
struct_resource();
+ struct_range();
addr();
escaped_str();
hex_string();
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index c5e2ec9303c5..6ac02bbb7df1 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1040,6 +1040,20 @@ static const struct printf_spec default_dec04_spec = {
};
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
char *resource_string(char *buf, char *end, struct resource *res,
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 = number(p, pend, resource_size(res), *specp);
} else {
- p = number(p, pend, res->start, *specp);
- if (res->start != res->end) {
- *p++ = '-';
- p = number(p, pend, res->end, *specp);
- }
+ p = hex_range(p, pend, res->start, res->end, *specp);
}
if (decode) {
if (res->flags & IORESOURCE_MEM_64)
@@ -1141,6 +1151,31 @@ char *resource_string(char *buf, char *end, struct resource *res,
}
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
char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
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);
}
+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)
{
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)
* - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
* - '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
* width which must be explicitly specified either as part of the
* 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);
case 'R':
case 'r':
- return resource_string(buf, end, ptr, spec, fmt);
+ return resource_or_range(fmt, buf, end, ptr, spec);
case 'h':
return hex_string(buf, end, ptr, spec, fmt);
case 'b':