66#include <linux/pci.h>
77#include <cxlmem.h>
88#include <cxlpci.h>
9+ #include <pmu.h>
910
1011#include "core.h"
1112
@@ -286,20 +287,23 @@ static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi,
286287}
287288
288289/**
289- * cxl_find_regblock () - Locate register blocks by type
290+ * cxl_find_regblock_instance () - Locate a register block by type / index
290291 * @pdev: The CXL PCI device to enumerate.
291292 * @type: Register Block Indicator id
292293 * @map: Enumeration output, clobbered on error
294+ * @index: Index into which particular instance of a regblock wanted in the
295+ * order found in register locator DVSEC.
293296 *
294297 * Return: 0 if register block enumerated, negative error code otherwise
295298 *
296299 * A CXL DVSEC may point to one or more register blocks, search for them
297- * by @type.
300+ * by @type and @index .
298301 */
299- int cxl_find_regblock (struct pci_dev * pdev , enum cxl_regloc_type type ,
300- struct cxl_register_map * map )
302+ int cxl_find_regblock_instance (struct pci_dev * pdev , enum cxl_regloc_type type ,
303+ struct cxl_register_map * map , int index )
301304{
302305 u32 regloc_size , regblocks ;
306+ int instance = 0 ;
303307 int regloc , i ;
304308
305309 map -> resource = CXL_RESOURCE_NONE ;
@@ -323,15 +327,74 @@ int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
323327 if (!cxl_decode_regblock (pdev , reg_lo , reg_hi , map ))
324328 continue ;
325329
326- if (map -> reg_type == type )
327- return 0 ;
330+ if (map -> reg_type == type ) {
331+ if (index == instance )
332+ return 0 ;
333+ instance ++ ;
334+ }
328335 }
329336
330337 map -> resource = CXL_RESOURCE_NONE ;
331338 return - ENODEV ;
332339}
340+ EXPORT_SYMBOL_NS_GPL (cxl_find_regblock_instance , CXL );
341+
342+ /**
343+ * cxl_find_regblock() - Locate register blocks by type
344+ * @pdev: The CXL PCI device to enumerate.
345+ * @type: Register Block Indicator id
346+ * @map: Enumeration output, clobbered on error
347+ *
348+ * Return: 0 if register block enumerated, negative error code otherwise
349+ *
350+ * A CXL DVSEC may point to one or more register blocks, search for them
351+ * by @type.
352+ */
353+ int cxl_find_regblock (struct pci_dev * pdev , enum cxl_regloc_type type ,
354+ struct cxl_register_map * map )
355+ {
356+ return cxl_find_regblock_instance (pdev , type , map , 0 );
357+ }
333358EXPORT_SYMBOL_NS_GPL (cxl_find_regblock , CXL );
334359
360+ /**
361+ * cxl_count_regblock() - Count instances of a given regblock type.
362+ * @pdev: The CXL PCI device to enumerate.
363+ * @type: Register Block Indicator id
364+ *
365+ * Some regblocks may be repeated. Count how many instances.
366+ *
367+ * Return: count of matching regblocks.
368+ */
369+ int cxl_count_regblock (struct pci_dev * pdev , enum cxl_regloc_type type )
370+ {
371+ struct cxl_register_map map ;
372+ int rc , count = 0 ;
373+
374+ while (1 ) {
375+ rc = cxl_find_regblock_instance (pdev , type , & map , count );
376+ if (rc )
377+ return count ;
378+ count ++ ;
379+ }
380+ }
381+ EXPORT_SYMBOL_NS_GPL (cxl_count_regblock , CXL );
382+
383+ int cxl_map_pmu_regs (struct pci_dev * pdev , struct cxl_pmu_regs * regs ,
384+ struct cxl_register_map * map )
385+ {
386+ struct device * dev = & pdev -> dev ;
387+ resource_size_t phys_addr ;
388+
389+ phys_addr = map -> resource ;
390+ regs -> pmu = devm_cxl_iomap_block (dev , phys_addr , CXL_PMU_REGMAP_SIZE );
391+ if (!regs -> pmu )
392+ return - ENOMEM ;
393+
394+ return 0 ;
395+ }
396+ EXPORT_SYMBOL_NS_GPL (cxl_map_pmu_regs , CXL );
397+
335398resource_size_t cxl_rcrb_to_component (struct device * dev ,
336399 resource_size_t rcrb ,
337400 enum cxl_rcrb which )
0 commit comments