]> Gentwo Git Trees - linux/.git/commitdiff
Merge branch 'for-6.19/cxl-prm' into cxl-for-next
authorDave Jiang <dave.jiang@intel.com>
Fri, 14 Nov 2025 17:54:34 +0000 (10:54 -0700)
committerDave Jiang <dave.jiang@intel.com>
Fri, 14 Nov 2025 18:11:46 +0000 (11:11 -0700)
- Simplify cxl_rd_ops allocation
- Group xor arithmetric setup code
- Remove local variable @inc in cxl_port_setup_targets()

1  2 
drivers/cxl/acpi.c
drivers/cxl/core/region.c
drivers/cxl/cxl.h

Simple merge
index d5840f7352cc018b91146b47f538241ddc81c92a,8cdb6a935289b625ddabd99db518645c26c35256..2cf5b29cefd22f70d0b90917b96e96f34e1feb99
@@@ -2968,129 -2923,28 +2967,119 @@@ static bool cxl_is_hpa_in_chunk(u64 hpa
        return false;
  }
  
- static bool has_hpa_to_spa(struct cxl_root_decoder *cxlrd)
- {
-       return cxlrd->ops && cxlrd->ops->hpa_to_spa;
- }
- static bool has_spa_to_hpa(struct cxl_root_decoder *cxlrd)
- {
-       return cxlrd->ops && cxlrd->ops->spa_to_hpa;
- }
 -u64 cxl_dpa_to_hpa(struct cxl_region *cxlr, const struct cxl_memdev *cxlmd,
 -                 u64 dpa)
 +#define CXL_POS_ZERO 0
 +/**
 + * cxl_validate_translation_params
 + * @eiw: encoded interleave ways
 + * @eig: encoded interleave granularity
 + * @pos: position in interleave
 + *
 + * Callers pass CXL_POS_ZERO when no position parameter needs validating.
 + *
 + * Returns: 0 on success, -EINVAL on first invalid parameter
 + */
 +int cxl_validate_translation_params(u8 eiw, u16 eig, int pos)
  {
 -      struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent);
 -      u64 dpa_offset, hpa_offset, bits_upper, mask_upper, hpa;
 -      struct cxl_region_params *p = &cxlr->params;
 -      struct cxl_endpoint_decoder *cxled = NULL;
 -      u16 eig = 0;
 -      u8 eiw = 0;
 -      int pos;
 +      int ways, gran;
  
 -      for (int i = 0; i < p->nr_targets; i++) {
 -              cxled = p->targets[i];
 -              if (cxlmd == cxled_to_memdev(cxled))
 -                      break;
 +      if (eiw_to_ways(eiw, &ways)) {
 +              pr_debug("%s: invalid eiw=%u\n", __func__, eiw);
 +              return -EINVAL;
        }
 -      if (!cxled || cxlmd != cxled_to_memdev(cxled))
 +      if (eig_to_granularity(eig, &gran)) {
 +              pr_debug("%s: invalid eig=%u\n", __func__, eig);
 +              return -EINVAL;
 +      }
 +      if (pos < 0 || pos >= ways) {
 +              pr_debug("%s: invalid pos=%d for ways=%u\n", __func__, pos,
 +                       ways);
 +              return -EINVAL;
 +      }
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL_FOR_MODULES(cxl_validate_translation_params, "cxl_translate");
 +
 +u64 cxl_calculate_dpa_offset(u64 hpa_offset, u8 eiw, u16 eig)
 +{
 +      u64 dpa_offset, bits_lower, bits_upper, temp;
 +      int ret;
 +
 +      ret = cxl_validate_translation_params(eiw, eig, CXL_POS_ZERO);
 +      if (ret)
                return ULLONG_MAX;
  
 -      pos = cxled->pos;
 -      ways_to_eiw(p->interleave_ways, &eiw);
 -      granularity_to_eig(p->interleave_granularity, &eig);
 +      /*
 +       * DPA offset: CXL Spec 3.2 Section 8.2.4.20.13
 +       * Lower bits [IG+7:0] pass through unchanged
 +       * (eiw < 8)
 +       *      Per spec: DPAOffset[51:IG+8] = (HPAOffset[51:IG+IW+8] >> IW)
 +       *      Clear the position bits to isolate upper section, then
 +       *      reverse the left shift by eiw that occurred during DPA->HPA
 +       * (eiw >= 8)
 +       *      Per spec: DPAOffset[51:IG+8] = HPAOffset[51:IG+IW] / 3
 +       *      Extract upper bits from the correct bit range and divide by 3
 +       *      to recover the original DPA upper bits
 +       */
 +      bits_lower = hpa_offset & GENMASK_ULL(eig + 7, 0);
 +      if (eiw < 8) {
 +              temp = hpa_offset &= ~GENMASK_ULL(eig + eiw + 8 - 1, 0);
 +              dpa_offset = temp >> eiw;
 +      } else {
 +              bits_upper = div64_u64(hpa_offset >> (eig + eiw), 3);
 +              dpa_offset = bits_upper << (eig + 8);
 +      }
 +      dpa_offset |= bits_lower;
 +
 +      return dpa_offset;
 +}
 +EXPORT_SYMBOL_FOR_MODULES(cxl_calculate_dpa_offset, "cxl_translate");
 +
 +int cxl_calculate_position(u64 hpa_offset, u8 eiw, u16 eig)
 +{
 +      unsigned int ways = 0;
 +      u64 shifted, rem;
 +      int pos, ret;
 +
 +      ret = cxl_validate_translation_params(eiw, eig, CXL_POS_ZERO);
 +      if (ret)
 +              return ret;
 +
 +      if (!eiw)
 +              /* position is 0 if no interleaving */
 +              return 0;
 +
 +      /*
 +       * Interleave position: CXL Spec 3.2 Section 8.2.4.20.13
 +       * eiw < 8
 +       *      Position is in the IW bits at HPA_OFFSET[IG+8+IW-1:IG+8].
 +       *      Per spec "remove IW bits starting with bit position IG+8"
 +       * eiw >= 8
 +       *      Position is not explicitly stored in HPA_OFFSET bits. It is
 +       *      derived from the modulo operation of the upper bits using
 +       *      the total number of interleave ways.
 +       */
 +      if (eiw < 8) {
 +              pos = (hpa_offset >> (eig + 8)) & GENMASK(eiw - 1, 0);
 +      } else {
 +              shifted = hpa_offset >> (eig + 8);
 +              eiw_to_ways(eiw, &ways);
 +              div64_u64_rem(shifted, ways, &rem);
 +              pos = rem;
 +      }
 +
 +      return pos;
 +}
 +EXPORT_SYMBOL_FOR_MODULES(cxl_calculate_position, "cxl_translate");
 +
 +u64 cxl_calculate_hpa_offset(u64 dpa_offset, int pos, u8 eiw, u16 eig)
 +{
 +      u64 mask_upper, hpa_offset, bits_upper;
 +      int ret;
 +
 +      ret = cxl_validate_translation_params(eiw, eig, pos);
 +      if (ret)
 +              return ULLONG_MAX;
  
        /*
         * The device position in the region interleave set was removed
Simple merge