Skip to content

Commit b70c2cf

Browse files
committed
cxl/hdm: Skip emulation when driver manages mem_enable
If the driver is allowed to enable memory operation itself then it can also turn on HDM decoder support at will. With this the second call to cxl_setup_hdm_decoder_from_dvsec(), when an HDM decoder is not committed, is not needed. Fixes: b777e9b ("cxl/hdm: Emulate HDM decoder from DVSEC range registers") Link: http://lore.kernel.org/r/20230220113657.000042e1@huawei.com Reported-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Fan Ni <fan.ni@samsung.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Link: https://lore.kernel.org/r/167703068474.185722.664126485486344246.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 82f0832 commit b70c2cf

File tree

3 files changed

+22
-15
lines changed

3 files changed

+22
-15
lines changed

drivers/cxl/core/hdm.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -717,19 +717,29 @@ static int cxl_setup_hdm_decoder_from_dvsec(struct cxl_port *port,
717717
return 0;
718718
}
719719

720-
static bool should_emulate_decoders(struct cxl_port *port)
720+
static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
721721
{
722-
struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev);
723-
void __iomem *hdm = cxlhdm->regs.hdm_decoder;
722+
struct cxl_hdm *cxlhdm;
723+
void __iomem *hdm;
724724
u32 ctrl;
725725
int i;
726726

727-
if (!is_cxl_endpoint(cxlhdm->port))
727+
if (!info)
728728
return false;
729729

730+
cxlhdm = dev_get_drvdata(&info->port->dev);
731+
hdm = cxlhdm->regs.hdm_decoder;
732+
730733
if (!hdm)
731734
return true;
732735

736+
/*
737+
* If HDM decoders are present and the driver is in control of
738+
* Mem_Enable skip DVSEC based emulation
739+
*/
740+
if (!info->mem_enabled)
741+
return false;
742+
733743
/*
734744
* If any decoders are committed already, there should not be any
735745
* emulated DVSEC decoders.
@@ -747,7 +757,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
747757
int *target_map, void __iomem *hdm, int which,
748758
u64 *dpa_base, struct cxl_endpoint_dvsec_info *info)
749759
{
750-
struct cxl_endpoint_decoder *cxled = NULL;
760+
struct cxl_endpoint_decoder *cxled;
751761
u64 size, base, skip, dpa_size;
752762
bool committed;
753763
u32 remainder;
@@ -758,12 +768,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
758768
unsigned char target_id[8];
759769
} target_list;
760770

761-
if (should_emulate_decoders(port))
771+
if (should_emulate_decoders(info))
762772
return cxl_setup_hdm_decoder_from_dvsec(port, cxld, which, info);
763773

764-
if (is_endpoint_decoder(&cxld->dev))
765-
cxled = to_cxl_endpoint_decoder(&cxld->dev);
766-
767774
ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which));
768775
base = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(which));
769776
size = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(which));
@@ -784,9 +791,6 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
784791
.end = base + size - 1,
785792
};
786793

787-
if (cxled && !committed && range_len(&info->dvsec_range[which]))
788-
return cxl_setup_hdm_decoder_from_dvsec(port, cxld, which, info);
789-
790794
/* decoders are enabled if committed */
791795
if (committed) {
792796
cxld->flags |= CXL_DECODER_F_ENABLE;
@@ -824,7 +828,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
824828
if (rc)
825829
return rc;
826830

827-
if (!cxled) {
831+
if (!info) {
828832
target_list.value =
829833
ioread64_hi_lo(hdm + CXL_HDM_DECODER0_TL_LOW(which));
830834
for (i = 0; i < cxld->interleave_ways; i++)
@@ -844,6 +848,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
844848
return -ENXIO;
845849
}
846850
skip = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_SKIP_LOW(which));
851+
cxled = to_cxl_endpoint_decoder(&cxld->dev);
847852
rc = devm_cxl_dpa_reserve(cxled, *dpa_base + skip, dpa_size, skip);
848853
if (rc) {
849854
dev_err(&port->dev,

drivers/cxl/cxl.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,13 +695,15 @@ int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint)
695695

696696
/**
697697
* struct cxl_endpoint_dvsec_info - Cached DVSEC info
698-
* @mem_enabled: cached value of mem_enabled in the DVSEC, PCIE_DEVICE
698+
* @mem_enabled: cached value of mem_enabled in the DVSEC at init time
699699
* @ranges: Number of active HDM ranges this device uses.
700+
* @port: endpoint port associated with this info instance
700701
* @dvsec_range: cached attributes of the ranges in the DVSEC, PCIE_DEVICE
701702
*/
702703
struct cxl_endpoint_dvsec_info {
703704
bool mem_enabled;
704705
int ranges;
706+
struct cxl_port *port;
705707
struct range dvsec_range[2];
706708
};
707709

drivers/cxl/port.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ static int cxl_switch_port_probe(struct cxl_port *port)
7878

7979
static int cxl_endpoint_port_probe(struct cxl_port *port)
8080
{
81+
struct cxl_endpoint_dvsec_info info = { .port = port };
8182
struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport);
82-
struct cxl_endpoint_dvsec_info info = { 0 };
8383
struct cxl_dev_state *cxlds = cxlmd->cxlds;
8484
struct cxl_hdm *cxlhdm;
8585
struct cxl_port *root;

0 commit comments

Comments
 (0)