Skip to content

Commit b777e9b

Browse files
davejiangdjbw
authored andcommitted
cxl/hdm: Emulate HDM decoder from DVSEC range registers
In the case where HDM decoder register block exists but is not programmed and at the same time the DVSEC range register range is active, populate the CXL decoder object 'cxl_decoder' with info from DVSEC range registers. Reviewed-by: Jonathan Cameron <[email protected]> Signed-off-by: Dave Jiang <[email protected]> Link: https://lore.kernel.org/r/167640368454.935665.13806415120298330717.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams <[email protected]>
1 parent 9de321e commit b777e9b

File tree

7 files changed

+45
-11
lines changed

7 files changed

+45
-11
lines changed

drivers/cxl/core/hdm.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -679,9 +679,34 @@ static int cxl_decoder_reset(struct cxl_decoder *cxld)
679679
return 0;
680680
}
681681

682+
static int cxl_setup_hdm_decoder_from_dvsec(struct cxl_port *port,
683+
struct cxl_decoder *cxld, int which,
684+
struct cxl_endpoint_dvsec_info *info)
685+
{
686+
if (!is_cxl_endpoint(port))
687+
return -EOPNOTSUPP;
688+
689+
if (!range_len(&info->dvsec_range[which]))
690+
return -ENOENT;
691+
692+
cxld->target_type = CXL_DECODER_EXPANDER;
693+
cxld->commit = NULL;
694+
cxld->reset = NULL;
695+
cxld->hpa_range = info->dvsec_range[which];
696+
697+
/*
698+
* Set the emulated decoder as locked pending additional support to
699+
* change the range registers at run time.
700+
*/
701+
cxld->flags |= CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK;
702+
port->commit_end = cxld->id;
703+
704+
return 0;
705+
}
706+
682707
static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
683708
int *target_map, void __iomem *hdm, int which,
684-
u64 *dpa_base)
709+
u64 *dpa_base, struct cxl_endpoint_dvsec_info *info)
685710
{
686711
struct cxl_endpoint_decoder *cxled = NULL;
687712
u64 size, base, skip, dpa_size;
@@ -717,6 +742,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
717742
.end = base + size - 1,
718743
};
719744

745+
if (cxled && !committed && range_len(&info->dvsec_range[which]))
746+
return cxl_setup_hdm_decoder_from_dvsec(port, cxld, which, info);
747+
720748
/* decoders are enabled if committed */
721749
if (committed) {
722750
cxld->flags |= CXL_DECODER_F_ENABLE;
@@ -790,7 +818,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
790818
* devm_cxl_enumerate_decoders - add decoder objects per HDM register set
791819
* @cxlhdm: Structure to populate with HDM capabilities
792820
*/
793-
int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
821+
int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
822+
struct cxl_endpoint_dvsec_info *info)
794823
{
795824
void __iomem *hdm = cxlhdm->regs.hdm_decoder;
796825
struct cxl_port *port = cxlhdm->port;
@@ -842,7 +871,8 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
842871
cxld = &cxlsd->cxld;
843872
}
844873

845-
rc = init_hdm_decoder(port, cxld, target_map, hdm, i, &dpa_base);
874+
rc = init_hdm_decoder(port, cxld, target_map, hdm, i,
875+
&dpa_base, info);
846876
if (rc) {
847877
put_device(&cxld->dev);
848878
return rc;

drivers/cxl/core/pci.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
426426
* Decoder Capability Enable.
427427
*/
428428
if (info->mem_enabled)
429-
return -EBUSY;
429+
return 0;
430430

431431
rc = devm_cxl_enable_hdm(&port->dev, cxlhdm);
432432
if (rc)

drivers/cxl/cxl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,8 @@ struct cxl_endpoint_dvsec_info {
644644

645645
struct cxl_hdm;
646646
struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port);
647-
int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm);
647+
int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
648+
struct cxl_endpoint_dvsec_info *info);
648649
int devm_cxl_add_passthrough_decoder(struct cxl_port *port);
649650
int cxl_dvsec_rr_decode(struct device *dev, int dvsec,
650651
struct cxl_endpoint_dvsec_info *info);

drivers/cxl/port.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static int cxl_port_probe(struct device *dev)
7878
}
7979
}
8080

81-
rc = devm_cxl_enumerate_decoders(cxlhdm);
81+
rc = devm_cxl_enumerate_decoders(cxlhdm, &info);
8282
if (rc) {
8383
dev_err(dev, "Couldn't enumerate decoders (%d)\n", rc);
8484
return rc;

tools/testing/cxl/test/cxl.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,8 @@ static int mock_decoder_reset(struct cxl_decoder *cxld)
701701
return 0;
702702
}
703703

704-
static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
704+
static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
705+
struct cxl_endpoint_dvsec_info *info)
705706
{
706707
struct cxl_port *port = cxlhdm->port;
707708
struct cxl_port *parent_port = to_cxl_port(port->dev.parent);

tools/testing/cxl/test/mock.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,16 +162,17 @@ int __wrap_devm_cxl_add_passthrough_decoder(struct cxl_port *port)
162162
}
163163
EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_passthrough_decoder, CXL);
164164

165-
int __wrap_devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
165+
int __wrap_devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
166+
struct cxl_endpoint_dvsec_info *info)
166167
{
167168
int rc, index;
168169
struct cxl_port *port = cxlhdm->port;
169170
struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
170171

171172
if (ops && ops->is_mock_port(port->uport))
172-
rc = ops->devm_cxl_enumerate_decoders(cxlhdm);
173+
rc = ops->devm_cxl_enumerate_decoders(cxlhdm, info);
173174
else
174-
rc = devm_cxl_enumerate_decoders(cxlhdm);
175+
rc = devm_cxl_enumerate_decoders(cxlhdm, info);
175176
put_cxl_mock_ops(index);
176177

177178
return rc;

tools/testing/cxl/test/mock.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ struct cxl_mock_ops {
2525
int (*devm_cxl_port_enumerate_dports)(struct cxl_port *port);
2626
struct cxl_hdm *(*devm_cxl_setup_hdm)(struct cxl_port *port);
2727
int (*devm_cxl_add_passthrough_decoder)(struct cxl_port *port);
28-
int (*devm_cxl_enumerate_decoders)(struct cxl_hdm *hdm);
28+
int (*devm_cxl_enumerate_decoders)(
29+
struct cxl_hdm *hdm, struct cxl_endpoint_dvsec_info *info);
2930
};
3031

3132
void register_cxl_mock_ops(struct cxl_mock_ops *ops);

0 commit comments

Comments
 (0)