Skip to content

Commit d717d7f

Browse files
jic23djbw
authored andcommitted
cxl: Add functions to get an instance of / count regblocks of a given type
Until the recently release CXL 3.0 specification, there was only ever one instance of any given register block pointed to by the Register Block Locator DVSEC. Now, the specification allows for multiple CXL PMU instances, each with their own register block. To enable this add cxl_find_regblock_instance() that takes an index parameter and use that to implement cxl_count_regblock() and cxl_find_regblock(). Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Link: https://lore.kernel.org/r/20230526095824.16336-3-Jonathan.Cameron@huawei.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 143f83e commit d717d7f

2 files changed

Lines changed: 56 additions & 6 deletions

File tree

drivers/cxl/core/regs.c

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -286,20 +286,23 @@ static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi,
286286
}
287287

288288
/**
289-
* cxl_find_regblock() - Locate register blocks by type
289+
* cxl_find_regblock_instance() - Locate a register block by type / index
290290
* @pdev: The CXL PCI device to enumerate.
291291
* @type: Register Block Indicator id
292292
* @map: Enumeration output, clobbered on error
293+
* @index: Index into which particular instance of a regblock wanted in the
294+
* order found in register locator DVSEC.
293295
*
294296
* Return: 0 if register block enumerated, negative error code otherwise
295297
*
296298
* A CXL DVSEC may point to one or more register blocks, search for them
297-
* by @type.
299+
* by @type and @index.
298300
*/
299-
int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
300-
struct cxl_register_map *map)
301+
int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type,
302+
struct cxl_register_map *map, int index)
301303
{
302304
u32 regloc_size, regblocks;
305+
int instance = 0;
303306
int regloc, i;
304307

305308
map->resource = CXL_RESOURCE_NONE;
@@ -323,15 +326,59 @@ int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
323326
if (!cxl_decode_regblock(pdev, reg_lo, reg_hi, map))
324327
continue;
325328

326-
if (map->reg_type == type)
327-
return 0;
329+
if (map->reg_type == type) {
330+
if (index == instance)
331+
return 0;
332+
instance++;
333+
}
328334
}
329335

330336
map->resource = CXL_RESOURCE_NONE;
331337
return -ENODEV;
332338
}
339+
EXPORT_SYMBOL_NS_GPL(cxl_find_regblock_instance, CXL);
340+
341+
/**
342+
* cxl_find_regblock() - Locate register blocks by type
343+
* @pdev: The CXL PCI device to enumerate.
344+
* @type: Register Block Indicator id
345+
* @map: Enumeration output, clobbered on error
346+
*
347+
* Return: 0 if register block enumerated, negative error code otherwise
348+
*
349+
* A CXL DVSEC may point to one or more register blocks, search for them
350+
* by @type.
351+
*/
352+
int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
353+
struct cxl_register_map *map)
354+
{
355+
return cxl_find_regblock_instance(pdev, type, map, 0);
356+
}
333357
EXPORT_SYMBOL_NS_GPL(cxl_find_regblock, CXL);
334358

359+
/**
360+
* cxl_count_regblock() - Count instances of a given regblock type.
361+
* @pdev: The CXL PCI device to enumerate.
362+
* @type: Register Block Indicator id
363+
*
364+
* Some regblocks may be repeated. Count how many instances.
365+
*
366+
* Return: count of matching regblocks.
367+
*/
368+
int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type)
369+
{
370+
struct cxl_register_map map;
371+
int rc, count = 0;
372+
373+
while (1) {
374+
rc = cxl_find_regblock_instance(pdev, type, &map, count);
375+
if (rc)
376+
return count;
377+
count++;
378+
}
379+
}
380+
EXPORT_SYMBOL_NS_GPL(cxl_count_regblock, CXL);
381+
335382
resource_size_t cxl_rcrb_to_component(struct device *dev,
336383
resource_size_t rcrb,
337384
enum cxl_rcrb which)

drivers/cxl/cxl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ int cxl_map_device_regs(struct device *dev, struct cxl_device_regs *regs,
260260
struct cxl_register_map *map);
261261

262262
enum cxl_regloc_type;
263+
int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type);
264+
int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type,
265+
struct cxl_register_map *map, int index);
263266
int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
264267
struct cxl_register_map *map);
265268

0 commit comments

Comments
 (0)