Skip to content

Commit a5fcd22

Browse files
committed
Merge branch 'for-6.3/cxl-rr-emu' into cxl/next
Pick up the CXL DVSEC range register emulation for v6.3, and resolve conflicts with the cxl_port_probe() split (from for-6.3/cxl-ram-region) and event handling (from for-6.3/cxl-events).
2 parents 5a6fe61 + 6980daa commit a5fcd22

File tree

10 files changed

+268
-150
lines changed

10 files changed

+268
-150
lines changed

drivers/cxl/core/hdm.c

Lines changed: 108 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,34 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
101101
BIT(CXL_CM_CAP_CAP_ID_HDM));
102102
}
103103

104+
static struct cxl_hdm *devm_cxl_setup_emulated_hdm(struct cxl_port *port,
105+
struct cxl_endpoint_dvsec_info *info)
106+
{
107+
struct device *dev = &port->dev;
108+
struct cxl_hdm *cxlhdm;
109+
110+
if (!info->mem_enabled)
111+
return ERR_PTR(-ENODEV);
112+
113+
cxlhdm = devm_kzalloc(dev, sizeof(*cxlhdm), GFP_KERNEL);
114+
if (!cxlhdm)
115+
return ERR_PTR(-ENOMEM);
116+
117+
cxlhdm->port = port;
118+
cxlhdm->decoder_count = info->ranges;
119+
cxlhdm->target_count = info->ranges;
120+
dev_set_drvdata(&port->dev, cxlhdm);
121+
122+
return cxlhdm;
123+
}
124+
104125
/**
105126
* devm_cxl_setup_hdm - map HDM decoder component registers
106127
* @port: cxl_port to map
128+
* @info: cached DVSEC range register info
107129
*/
108-
struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port)
130+
struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port,
131+
struct cxl_endpoint_dvsec_info *info)
109132
{
110133
struct device *dev = &port->dev;
111134
struct cxl_hdm *cxlhdm;
@@ -119,6 +142,9 @@ struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port)
119142
cxlhdm->port = port;
120143
crb = ioremap(port->component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE);
121144
if (!crb) {
145+
if (info && info->mem_enabled)
146+
return devm_cxl_setup_emulated_hdm(port, info);
147+
122148
dev_err(dev, "No component registers mapped\n");
123149
return ERR_PTR(-ENXIO);
124150
}
@@ -688,9 +714,60 @@ static int cxl_decoder_reset(struct cxl_decoder *cxld)
688714
return 0;
689715
}
690716

717+
static int cxl_setup_hdm_decoder_from_dvsec(struct cxl_port *port,
718+
struct cxl_decoder *cxld, int which,
719+
struct cxl_endpoint_dvsec_info *info)
720+
{
721+
if (!is_cxl_endpoint(port))
722+
return -EOPNOTSUPP;
723+
724+
if (!range_len(&info->dvsec_range[which]))
725+
return -ENOENT;
726+
727+
cxld->target_type = CXL_DECODER_EXPANDER;
728+
cxld->commit = NULL;
729+
cxld->reset = NULL;
730+
cxld->hpa_range = info->dvsec_range[which];
731+
732+
/*
733+
* Set the emulated decoder as locked pending additional support to
734+
* change the range registers at run time.
735+
*/
736+
cxld->flags |= CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK;
737+
port->commit_end = cxld->id;
738+
739+
return 0;
740+
}
741+
742+
static bool should_emulate_decoders(struct cxl_port *port)
743+
{
744+
struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev);
745+
void __iomem *hdm = cxlhdm->regs.hdm_decoder;
746+
u32 ctrl;
747+
int i;
748+
749+
if (!is_cxl_endpoint(cxlhdm->port))
750+
return false;
751+
752+
if (!hdm)
753+
return true;
754+
755+
/*
756+
* If any decoders are committed already, there should not be any
757+
* emulated DVSEC decoders.
758+
*/
759+
for (i = 0; i < cxlhdm->decoder_count; i++) {
760+
ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(i));
761+
if (FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl))
762+
return false;
763+
}
764+
765+
return true;
766+
}
767+
691768
static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
692769
int *target_map, void __iomem *hdm, int which,
693-
u64 *dpa_base)
770+
u64 *dpa_base, struct cxl_endpoint_dvsec_info *info)
694771
{
695772
struct cxl_endpoint_decoder *cxled = NULL;
696773
u64 size, base, skip, dpa_size;
@@ -703,6 +780,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
703780
unsigned char target_id[8];
704781
} target_list;
705782

783+
if (should_emulate_decoders(port))
784+
return cxl_setup_hdm_decoder_from_dvsec(port, cxld, which, info);
785+
706786
if (is_endpoint_decoder(&cxld->dev))
707787
cxled = to_cxl_endpoint_decoder(&cxld->dev);
708788

@@ -726,6 +806,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
726806
.end = base + size - 1,
727807
};
728808

809+
if (cxled && !committed && range_len(&info->dvsec_range[which]))
810+
return cxl_setup_hdm_decoder_from_dvsec(port, cxld, which, info);
811+
729812
/* decoders are enabled if committed */
730813
if (committed) {
731814
cxld->flags |= CXL_DECODER_F_ENABLE;
@@ -798,18 +881,15 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
798881
return 0;
799882
}
800883

801-
/**
802-
* devm_cxl_enumerate_decoders - add decoder objects per HDM register set
803-
* @cxlhdm: Structure to populate with HDM capabilities
804-
*/
805-
int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
884+
static void cxl_settle_decoders(struct cxl_hdm *cxlhdm)
806885
{
807886
void __iomem *hdm = cxlhdm->regs.hdm_decoder;
808-
struct cxl_port *port = cxlhdm->port;
809-
int i, committed;
810-
u64 dpa_base = 0;
887+
int committed, i;
811888
u32 ctrl;
812889

890+
if (!hdm)
891+
return;
892+
813893
/*
814894
* Since the register resource was recently claimed via request_region()
815895
* be careful about trusting the "not-committed" status until the commit
@@ -826,6 +906,22 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
826906
/* ensure that future checks of committed can be trusted */
827907
if (committed != cxlhdm->decoder_count)
828908
msleep(20);
909+
}
910+
911+
/**
912+
* devm_cxl_enumerate_decoders - add decoder objects per HDM register set
913+
* @cxlhdm: Structure to populate with HDM capabilities
914+
* @info: cached DVSEC range register info
915+
*/
916+
int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
917+
struct cxl_endpoint_dvsec_info *info)
918+
{
919+
void __iomem *hdm = cxlhdm->regs.hdm_decoder;
920+
struct cxl_port *port = cxlhdm->port;
921+
int i;
922+
u64 dpa_base = 0;
923+
924+
cxl_settle_decoders(cxlhdm);
829925

830926
for (i = 0; i < cxlhdm->decoder_count; i++) {
831927
int target_map[CXL_DECODER_MAX_INTERLEAVE] = { 0 };
@@ -856,7 +952,8 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
856952
cxld = &cxlsd->cxld;
857953
}
858954

859-
rc = init_hdm_decoder(port, cxld, target_map, hdm, i, &dpa_base);
955+
rc = init_hdm_decoder(port, cxld, target_map, hdm, i,
956+
&dpa_base, info);
860957
if (rc) {
861958
dev_warn(&port->dev,
862959
"Failed to initialize decoder%d.%d\n",

0 commit comments

Comments
 (0)