OSDN Git Service

Merge branch 'for-6.2/cxl-xor' into for-6.2/cxl
authorDan Williams <dan.j.williams@intel.com>
Mon, 5 Dec 2022 20:32:11 +0000 (12:32 -0800)
committerDan Williams <dan.j.williams@intel.com>
Mon, 5 Dec 2022 20:32:11 +0000 (12:32 -0800)
Pick up support for "XOR" interleave math when parsing ACPI CFMWS window
structures. Fix up conflicts with the RCH emulation already pending in
cxl/next.

1  2 
drivers/cxl/acpi.c
drivers/cxl/core/port.c
drivers/cxl/cxl.h
tools/testing/cxl/test/cxl.c

  #include "cxlpci.h"
  #include "cxl.h"
  
 +#define CXL_RCRB_SIZE SZ_8K
 +
+ struct cxl_cxims_data {
+       int nr_maps;
+       u64 xormaps[];
+ };
+ /*
+  * Find a targets entry (n) in the host bridge interleave list.
+  * CXL Specfication 3.0 Table 9-22
+  */
+ static int cxl_xor_calc_n(u64 hpa, struct cxl_cxims_data *cximsd, int iw,
+                         int ig)
+ {
+       int i = 0, n = 0;
+       u8 eiw;
+       /* IW: 2,4,6,8,12,16 begin building 'n' using xormaps */
+       if (iw != 3) {
+               for (i = 0; i < cximsd->nr_maps; i++)
+                       n |= (hweight64(hpa & cximsd->xormaps[i]) & 1) << i;
+       }
+       /* IW: 3,6,12 add a modulo calculation to 'n' */
+       if (!is_power_of_2(iw)) {
+               if (ways_to_cxl(iw, &eiw))
+                       return -1;
+               hpa &= GENMASK_ULL(51, eiw + ig);
+               n |= do_div(hpa, 3) << i;
+       }
+       return n;
+ }
+ static struct cxl_dport *cxl_hb_xor(struct cxl_root_decoder *cxlrd, int pos)
+ {
+       struct cxl_cxims_data *cximsd = cxlrd->platform_data;
+       struct cxl_switch_decoder *cxlsd = &cxlrd->cxlsd;
+       struct cxl_decoder *cxld = &cxlsd->cxld;
+       int ig = cxld->interleave_granularity;
+       int iw = cxld->interleave_ways;
+       int n = 0;
+       u64 hpa;
+       if (dev_WARN_ONCE(&cxld->dev,
+                         cxld->interleave_ways != cxlsd->nr_targets,
+                         "misconfigured root decoder\n"))
+               return NULL;
+       hpa = cxlrd->res->start + pos * ig;
+       /* Entry (n) is 0 for no interleave (iw == 1) */
+       if (iw != 1)
+               n = cxl_xor_calc_n(hpa, cximsd, iw, ig);
+       if (n < 0)
+               return NULL;
+       return cxlrd->cxlsd.target[n];
+ }
+ struct cxl_cxims_context {
+       struct device *dev;
+       struct cxl_root_decoder *cxlrd;
+ };
+ static int cxl_parse_cxims(union acpi_subtable_headers *header, void *arg,
+                          const unsigned long end)
+ {
+       struct acpi_cedt_cxims *cxims = (struct acpi_cedt_cxims *)header;
+       struct cxl_cxims_context *ctx = arg;
+       struct cxl_root_decoder *cxlrd = ctx->cxlrd;
+       struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld;
+       struct device *dev = ctx->dev;
+       struct cxl_cxims_data *cximsd;
+       unsigned int hbig, nr_maps;
+       int rc;
+       rc = cxl_to_granularity(cxims->hbig, &hbig);
+       if (rc)
+               return rc;
+       /* Does this CXIMS entry apply to the given CXL Window? */
+       if (hbig != cxld->interleave_granularity)
+               return 0;
+       /* IW 1,3 do not use xormaps and skip this parsing entirely */
+       if (is_power_of_2(cxld->interleave_ways))
+               /* 2, 4, 8, 16 way */
+               nr_maps = ilog2(cxld->interleave_ways);
+       else
+               /* 6, 12 way */
+               nr_maps = ilog2(cxld->interleave_ways / 3);
+       if (cxims->nr_xormaps < nr_maps) {
+               dev_dbg(dev, "CXIMS nr_xormaps[%d] expected[%d]\n",
+                       cxims->nr_xormaps, nr_maps);
+               return -ENXIO;
+       }
+       cximsd = devm_kzalloc(dev, struct_size(cximsd, xormaps, nr_maps),
+                             GFP_KERNEL);
+       if (!cximsd)
+               return -ENOMEM;
+       memcpy(cximsd->xormaps, cxims->xormap_list,
+              nr_maps * sizeof(*cximsd->xormaps));
+       cximsd->nr_maps = nr_maps;
+       cxlrd->platform_data = cximsd;
+       return 0;
+ }
  static unsigned long cfmws_to_decoder_flags(int restrictions)
  {
        unsigned long flags = CXL_DECODER_F_ENABLE;
Simple merge
Simple merge
  #include <cxlmem.h>
  #include "mock.h"
  
+ static int interleave_arithmetic;
  #define NR_CXL_HOST_BRIDGES 2
  #define NR_CXL_SINGLE_HOST 1
 +#define NR_CXL_RCH 1
  #define NR_CXL_ROOT_PORTS 2
  #define NR_CXL_SWITCH_PORTS 2
  #define NR_CXL_PORT_DECODERS 8
@@@ -135,6 -128,18 +137,22 @@@ static struct 
                struct acpi_cedt_cfmws cfmws;
                u32 target[1];
        } cfmws5;
 -              u32 target[2];
+       struct {
+               struct acpi_cedt_cfmws cfmws;
 -              u32 target[4];
++              u32 target[1];
+       } cfmws6;
+       struct {
+               struct acpi_cedt_cfmws cfmws;
++              u32 target[2];
+       } cfmws7;
+       struct {
++              struct acpi_cedt_cfmws cfmws;
++              u32 target[4];
++      } cfmws8;
++      struct {
+               struct acpi_cedt_cxims cxims;
+               u64 xormap_list[2];
+       } cxims0;
  } __packed mock_cedt = {
        .cedt = {
                .header = {
                                .type = ACPI_CEDT_TYPE_CFMWS,
                                .length = sizeof(mock_cedt.cfmws5),
                        },
 -      .cfmws6 = {
 +                      .interleave_ways = 0,
 +                      .granularity = 4,
 +                      .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
 +                                      ACPI_CEDT_CFMWS_RESTRICT_VOLATILE,
 +                      .qtg_id = 5,
 +                      .window_size = SZ_256M,
 +              },
 +              .target = { 3 },
 +      },
++      /* .cfmws6,7,8 use ACPI_CEDT_CFMWS_ARITHMETIC_XOR */
++      .cfmws6 = {
++              .cfmws = {
++                      .header = {
++                              .type = ACPI_CEDT_TYPE_CFMWS,
++                              .length = sizeof(mock_cedt.cfmws6),
++                      },
+                       .interleave_arithmetic = ACPI_CEDT_CFMWS_ARITHMETIC_XOR,
+                       .interleave_ways = 0,
+                       .granularity = 4,
+                       .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
+                                       ACPI_CEDT_CFMWS_RESTRICT_PMEM,
+                       .qtg_id = 0,
+                       .window_size = SZ_256M * 8UL,
+               },
+               .target = { 0, },
+       },
 -                              .length = sizeof(mock_cedt.cfmws6),
++      .cfmws7 = {
+               .cfmws = {
+                       .header = {
+                               .type = ACPI_CEDT_TYPE_CFMWS,
 -      .cfmws7 = {
++                              .length = sizeof(mock_cedt.cfmws7),
+                       },
+                       .interleave_arithmetic = ACPI_CEDT_CFMWS_ARITHMETIC_XOR,
+                       .interleave_ways = 1,
+                       .granularity = 0,
+                       .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
+                                       ACPI_CEDT_CFMWS_RESTRICT_PMEM,
+                       .qtg_id = 1,
+                       .window_size = SZ_256M * 8UL,
+               },
+               .target = { 0, 1, },
+       },
 -                              .length = sizeof(mock_cedt.cfmws7),
++      .cfmws8 = {
+               .cfmws = {
+                       .header = {
+                               .type = ACPI_CEDT_TYPE_CFMWS,
++                              .length = sizeof(mock_cedt.cfmws8),
+                       },
+                       .interleave_arithmetic = ACPI_CEDT_CFMWS_ARITHMETIC_XOR,
+                       .interleave_ways = 2,
+                       .granularity = 0,
+                       .restrictions = ACPI_CEDT_CFMWS_RESTRICT_TYPE3 |
+                                       ACPI_CEDT_CFMWS_RESTRICT_PMEM,
+                       .qtg_id = 0,
+                       .window_size = SZ_256M * 16UL,
+               },
+               .target = { 0, 1, 0, 1, },
+       },
+       .cxims0 = {
+               .cxims = {
+                       .header = {
+                               .type = ACPI_CEDT_TYPE_CXIMS,
+                               .length = sizeof(mock_cedt.cxims0),
+                       },
+                       .hbig = 0,
+                       .nr_xormaps = 2,
+               },
+               .xormap_list = { 0x404100, 0x808200, },
+       },
  };
  
 -struct acpi_cedt_cfmws *mock_cfmws[8] = {
 +struct acpi_cedt_cfmws *mock_cfmws[] = {
        [0] = &mock_cedt.cfmws0.cfmws,
        [1] = &mock_cedt.cfmws1.cfmws,
        [2] = &mock_cedt.cfmws2.cfmws,
        [3] = &mock_cedt.cfmws3.cfmws,
        [4] = &mock_cedt.cfmws4.cfmws,
 -      /* Modulo Math above, XOR Math below */
        [5] = &mock_cedt.cfmws5.cfmws,
 -#define CFMWS_MOD_ARRAY_END   4
 -#define CFMWS_XOR_ARRAY_START 5
 -#define CFMWS_XOR_ARRAY_END   7
++      /* Modulo Math above, XOR Math below */
+       [6] = &mock_cedt.cfmws6.cfmws,
+       [7] = &mock_cedt.cfmws7.cfmws,
++      [8] = &mock_cedt.cfmws8.cfmws,
+ };
+ static int cfmws_start;
+ static int cfmws_end;
+ #define CFMWS_MOD_ARRAY_START 0
++#define CFMWS_MOD_ARRAY_END   5
++#define CFMWS_XOR_ARRAY_START 6
++#define CFMWS_XOR_ARRAY_END   8
+ struct acpi_cedt_cxims *mock_cxims[1] = {
+       [0] = &mock_cedt.cxims0.cxims,
  };
  
  struct cxl_mock_res {
@@@ -345,10 -401,10 +438,10 @@@ static int populate_cedt(void
                chbs->length = size;
        }
  
-       for (i = 0; i < ARRAY_SIZE(mock_cfmws); i++) {
+       for (i = cfmws_start; i <= cfmws_end; i++) {
                struct acpi_cedt_cfmws *window = mock_cfmws[i];
  
 -              res = alloc_mock_res(window->window_size);
 +              res = alloc_mock_res(window->window_size, SZ_256M);
                if (!res)
                        return -ENOMEM;
                window->base_hpa = res->range.start;