• Dan Williams's avatar
    cxl/mem: Introduce 'struct cxl_regs' for "composable" CXL devices · 8ac75dd6
    Dan Williams authored
    CXL MMIO register blocks are organized by device type and capabilities.
    There are Component registers, Device registers (yes, an ambiguous
    name), and Memory Device registers (a specific extension of Device
    registers).
    
    It is possible for a given device instance (endpoint or port) to
    implement register sets from multiple of the above categories.
    
    The driver code that enumerates and maps the registers is type specific
    so it is useful to have a dedicated type and helpers for each block
    type.
    
    At the same time, once the registers are mapped the origin type does not
    matter. It is overly pedantic to reference the register block type in
    code that is using the registers.
    
    In preparation for the endpoint driver to incorporate Component registers
    into its MMIO operations reorganize the registers to allow typed
    enumeration + mapping, but anonymous usage. With the end state of
    'struct cxl_regs' to be:
    
    struct cxl_regs {
    	union {
    		struct {
    			CXL_DEVICE_REGS();
    		};
    		struct cxl_device_regs device_regs;
    	};
    	union {
    		struct {
    			CXL_COMPONENT_REGS();
    		};
    		struct cxl_component_regs component_regs;
    	};
    };
    
    With this arrangement the driver can share component init code with
    ports, but when using the registers it can directly reference the
    component register block type by name without the 'component_regs'
    prefix.
    
    So, map + enumerate can be shared across drivers of different CXL
    classes e.g.:
    
    void cxl_setup_device_regs(struct device *dev, void __iomem *base,
    			   struct cxl_device_regs *regs);
    
    void cxl_setup_component_regs(struct device *dev, void __iomem *base,
    			      struct cxl_component_regs *regs);
    
    ...while inline usage in the driver need not indicate where the
    registers came from:
    
    readl(cxlm->regs.mbox + MBOX_OFFSET);
    readl(cxlm->regs.hdm + HDM_OFFSET);
    
    ...instead of:
    
    readl(cxlm->regs.device_regs.mbox + MBOX_OFFSET);
    readl(cxlm->regs.component_regs.hdm + HDM_OFFSET);
    
    This complexity of the definition in .h yields improvement in code
    readability in .c while maintaining type-safety for organization of
    setup code. It prepares the implementation to maintain organization in
    the face of CXL devices that compose register interfaces consisting of
    multiple types.
    
    Given that this new container is named 'regs' rename the common register
    base pointer @base, and fixup the kernel-doc for the missing @cxlmd
    description.
    Reviewed-by: default avatarBen Widawsky <ben.widawsky@intel.com>
    Reviewed-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
    Cc: Christoph Hellwig <hch@lst.de>
    Link: https://lore.kernel.org/r/162096971451.1865304.13540251513463515153.stgit@dwillia2-desk3.amr.corp.intel.comSigned-off-by: default avatarDan Williams <dan.j.williams@intel.com>
    8ac75dd6
mem.c 41.8 KB