]> Git Repo - linux.git/blob - drivers/cxl/core/trace.c
blk-core: use pr_warn_ratelimited() in bio_check_ro()
[linux.git] / drivers / cxl / core / trace.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2022 Intel Corporation. All rights reserved. */
3
4 #include <cxl.h>
5 #include "core.h"
6
7 #define CREATE_TRACE_POINTS
8 #include "trace.h"
9
10 static bool cxl_is_hpa_in_range(u64 hpa, struct cxl_region *cxlr, int pos)
11 {
12         struct cxl_region_params *p = &cxlr->params;
13         int gran = p->interleave_granularity;
14         int ways = p->interleave_ways;
15         u64 offset;
16
17         /* Is the hpa within this region at all */
18         if (hpa < p->res->start || hpa > p->res->end) {
19                 dev_dbg(&cxlr->dev,
20                         "Addr trans fail: hpa 0x%llx not in region\n", hpa);
21                 return false;
22         }
23
24         /* Is the hpa in an expected chunk for its pos(-ition) */
25         offset = hpa - p->res->start;
26         offset = do_div(offset, gran * ways);
27         if ((offset >= pos * gran) && (offset < (pos + 1) * gran))
28                 return true;
29
30         dev_dbg(&cxlr->dev,
31                 "Addr trans fail: hpa 0x%llx not in expected chunk\n", hpa);
32
33         return false;
34 }
35
36 static u64 cxl_dpa_to_hpa(u64 dpa,  struct cxl_region *cxlr,
37                           struct cxl_endpoint_decoder *cxled)
38 {
39         u64 dpa_offset, hpa_offset, bits_upper, mask_upper, hpa;
40         struct cxl_region_params *p = &cxlr->params;
41         int pos = cxled->pos;
42         u16 eig = 0;
43         u8 eiw = 0;
44
45         ways_to_eiw(p->interleave_ways, &eiw);
46         granularity_to_eig(p->interleave_granularity, &eig);
47
48         /*
49          * The device position in the region interleave set was removed
50          * from the offset at HPA->DPA translation. To reconstruct the
51          * HPA, place the 'pos' in the offset.
52          *
53          * The placement of 'pos' in the HPA is determined by interleave
54          * ways and granularity and is defined in the CXL Spec 3.0 Section
55          * 8.2.4.19.13 Implementation Note: Device Decode Logic
56          */
57
58         /* Remove the dpa base */
59         dpa_offset = dpa - cxl_dpa_resource_start(cxled);
60
61         mask_upper = GENMASK_ULL(51, eig + 8);
62
63         if (eiw < 8) {
64                 hpa_offset = (dpa_offset & mask_upper) << eiw;
65                 hpa_offset |= pos << (eig + 8);
66         } else {
67                 bits_upper = (dpa_offset & mask_upper) >> (eig + 8);
68                 bits_upper = bits_upper * 3;
69                 hpa_offset = ((bits_upper << (eiw - 8)) + pos) << (eig + 8);
70         }
71
72         /* The lower bits remain unchanged */
73         hpa_offset |= dpa_offset & GENMASK_ULL(eig + 7, 0);
74
75         /* Apply the hpa_offset to the region base address */
76         hpa = hpa_offset + p->res->start;
77
78         if (!cxl_is_hpa_in_range(hpa, cxlr, cxled->pos))
79                 return ULLONG_MAX;
80
81         return hpa;
82 }
83
84 u64 cxl_trace_hpa(struct cxl_region *cxlr, struct cxl_memdev *cxlmd,
85                   u64 dpa)
86 {
87         struct cxl_region_params *p = &cxlr->params;
88         struct cxl_endpoint_decoder *cxled = NULL;
89
90         for (int i = 0; i <  p->nr_targets; i++) {
91                 cxled = p->targets[i];
92                 if (cxlmd == cxled_to_memdev(cxled))
93                         break;
94         }
95         if (!cxled || cxlmd != cxled_to_memdev(cxled))
96                 return ULLONG_MAX;
97
98         return cxl_dpa_to_hpa(dpa, cxlr, cxled);
99 }
This page took 0.037811 seconds and 4 git commands to generate.