Skip to content

Commit 9de321e

Browse files
davejiangdjbw
authored andcommitted
cxl/pci: Refactor cxl_hdm_decode_init()
With the previous refactoring of DVSEC range registers out of cxl_hdm_decode_init(), it basically becomes a skeleton function. Squash __cxl_hdm_decode_init() with cxl_hdm_decode_init() to simplify the code. cxl_hdm_decode_init() now returns more error codes than just -EBUSY. Reviewed-by: Jonathan Cameron <[email protected]> Signed-off-by: Dave Jiang <[email protected]> Link: https://lore.kernel.org/r/167640367916.935665.12898404758336059003.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams <[email protected]>
1 parent 59c3368 commit 9de321e

File tree

1 file changed

+54
-81
lines changed

1 file changed

+54
-81
lines changed

drivers/cxl/core/pci.c

Lines changed: 54 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -259,80 +259,6 @@ static int devm_cxl_enable_hdm(struct device *host, struct cxl_hdm *cxlhdm)
259259
return devm_add_action_or_reset(host, disable_hdm, cxlhdm);
260260
}
261261

262-
static bool __cxl_hdm_decode_init(struct cxl_dev_state *cxlds,
263-
struct cxl_hdm *cxlhdm,
264-
struct cxl_endpoint_dvsec_info *info)
265-
{
266-
void __iomem *hdm = cxlhdm->regs.hdm_decoder;
267-
struct cxl_port *port = cxlhdm->port;
268-
struct device *dev = cxlds->dev;
269-
struct cxl_port *root;
270-
int i, rc, allowed;
271-
u32 global_ctrl;
272-
273-
global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET);
274-
275-
/*
276-
* If the HDM Decoder Capability is already enabled then assume
277-
* that some other agent like platform firmware set it up.
278-
*/
279-
if (global_ctrl & CXL_HDM_DECODER_ENABLE) {
280-
rc = devm_cxl_enable_mem(&port->dev, cxlds);
281-
if (rc)
282-
return false;
283-
return true;
284-
}
285-
286-
root = to_cxl_port(port->dev.parent);
287-
while (!is_cxl_root(root) && is_cxl_port(root->dev.parent))
288-
root = to_cxl_port(root->dev.parent);
289-
if (!is_cxl_root(root)) {
290-
dev_err(dev, "Failed to acquire root port for HDM enable\n");
291-
return false;
292-
}
293-
294-
for (i = 0, allowed = 0; info->mem_enabled && i < info->ranges; i++) {
295-
struct device *cxld_dev;
296-
297-
cxld_dev = device_find_child(&root->dev, &info->dvsec_range[i],
298-
dvsec_range_allowed);
299-
if (!cxld_dev) {
300-
dev_dbg(dev, "DVSEC Range%d denied by platform\n", i);
301-
continue;
302-
}
303-
dev_dbg(dev, "DVSEC Range%d allowed by platform\n", i);
304-
put_device(cxld_dev);
305-
allowed++;
306-
}
307-
308-
if (!allowed) {
309-
cxl_set_mem_enable(cxlds, 0);
310-
info->mem_enabled = 0;
311-
}
312-
313-
/*
314-
* Per CXL 2.0 Section 8.1.3.8.3 and 8.1.3.8.4 DVSEC CXL Range 1 Base
315-
* [High,Low] when HDM operation is enabled the range register values
316-
* are ignored by the device, but the spec also recommends matching the
317-
* DVSEC Range 1,2 to HDM Decoder Range 0,1. So, non-zero info->ranges
318-
* are expected even though Linux does not require or maintain that
319-
* match. If at least one DVSEC range is enabled and allowed, skip HDM
320-
* Decoder Capability Enable.
321-
*/
322-
if (info->mem_enabled)
323-
return false;
324-
325-
rc = devm_cxl_enable_hdm(&port->dev, cxlhdm);
326-
if (rc)
327-
return false;
328-
329-
rc = devm_cxl_enable_mem(&port->dev, cxlds);
330-
if (rc)
331-
return false;
332-
333-
return true;
334-
}
335-
336262
int cxl_dvsec_rr_decode(struct device *dev, int d,
337263
struct cxl_endpoint_dvsec_info *info)
338264
{
@@ -447,19 +373,66 @@ EXPORT_SYMBOL_NS_GPL(cxl_dvsec_rr_decode, CXL);
447373
int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
448374
struct cxl_endpoint_dvsec_info *info)
449375
{
376+
void __iomem *hdm = cxlhdm->regs.hdm_decoder;
377+
struct cxl_port *port = cxlhdm->port;
450378
struct device *dev = cxlds->dev;
379+
struct cxl_port *root;
380+
int i, rc, allowed;
381+
u32 global_ctrl;
382+
383+
global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET);
451384

452385
/*
453-
* If DVSEC ranges are being used instead of HDM decoder registers there
454-
* is no use in trying to manage those.
386+
* If the HDM Decoder Capability is already enabled then assume
387+
* that some other agent like platform firmware set it up.
455388
*/
456-
if (!__cxl_hdm_decode_init(cxlds, cxlhdm, info)) {
457-
dev_err(dev,
458-
"Legacy range registers configuration prevents HDM operation.\n");
459-
return -EBUSY;
389+
if (global_ctrl & CXL_HDM_DECODER_ENABLE)
390+
return devm_cxl_enable_mem(&port->dev, cxlds);
391+
392+
root = to_cxl_port(port->dev.parent);
393+
while (!is_cxl_root(root) && is_cxl_port(root->dev.parent))
394+
root = to_cxl_port(root->dev.parent);
395+
if (!is_cxl_root(root)) {
396+
dev_err(dev, "Failed to acquire root port for HDM enable\n");
397+
return -ENODEV;
460398
}
461399

462-
return 0;
400+
for (i = 0, allowed = 0; info->mem_enabled && i < info->ranges; i++) {
401+
struct device *cxld_dev;
402+
403+
cxld_dev = device_find_child(&root->dev, &info->dvsec_range[i],
404+
dvsec_range_allowed);
405+
if (!cxld_dev) {
406+
dev_dbg(dev, "DVSEC Range%d denied by platform\n", i);
407+
continue;
408+
}
409+
dev_dbg(dev, "DVSEC Range%d allowed by platform\n", i);
410+
put_device(cxld_dev);
411+
allowed++;
412+
}
413+
414+
if (!allowed) {
415+
cxl_set_mem_enable(cxlds, 0);
416+
info->mem_enabled = 0;
417+
}
418+
419+
/*
420+
* Per CXL 2.0 Section 8.1.3.8.3 and 8.1.3.8.4 DVSEC CXL Range 1 Base
421+
* [High,Low] when HDM operation is enabled the range register values
422+
* are ignored by the device, but the spec also recommends matching the
423+
* DVSEC Range 1,2 to HDM Decoder Range 0,1. So, non-zero info->ranges
424+
* are expected even though Linux does not require or maintain that
425+
* match. If at least one DVSEC range is enabled and allowed, skip HDM
426+
* Decoder Capability Enable.
427+
*/
428+
if (info->mem_enabled)
429+
return -EBUSY;
430+
431+
rc = devm_cxl_enable_hdm(&port->dev, cxlhdm);
432+
if (rc)
433+
return rc;
434+
435+
return devm_cxl_enable_mem(&port->dev, cxlds);
463436
}
464437
EXPORT_SYMBOL_NS_GPL(cxl_hdm_decode_init, CXL);
465438

0 commit comments

Comments
 (0)