Commit ca899f40 authored by Dan Williams's avatar Dan Williams

Merge branch 'for-6.3/cxl-autodetect-fixes' into for-6.4/cxl

Pick up late v6.3 fixes for v6.4.
parents 856ef55e c841ecd8
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2022 Intel Corporation. All rights reserved. */ /* Copyright(c) 2022 Intel Corporation. All rights reserved. */
#include <linux/io-64-nonatomic-hi-lo.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -93,8 +92,9 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb, ...@@ -93,8 +92,9 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
cxl_probe_component_regs(&port->dev, crb, &map.component_map); cxl_probe_component_regs(&port->dev, crb, &map.component_map);
if (!map.component_map.hdm_decoder.valid) { if (!map.component_map.hdm_decoder.valid) {
dev_err(&port->dev, "HDM decoder registers invalid\n"); dev_dbg(&port->dev, "HDM decoder registers not implemented\n");
return -ENXIO; /* unique error code to indicate no HDM decoder capability */
return -ENODEV;
} }
return cxl_map_component_regs(&port->dev, regs, &map, return cxl_map_component_regs(&port->dev, regs, &map,
...@@ -130,6 +130,14 @@ static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info) ...@@ -130,6 +130,14 @@ static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
*/ */
for (i = 0; i < cxlhdm->decoder_count; i++) { for (i = 0; i < cxlhdm->decoder_count; i++) {
ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(i)); ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(i));
dev_dbg(&info->port->dev,
"decoder%d.%d: committed: %ld base: %#x_%.8x size: %#x_%.8x\n",
info->port->id, i,
FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl),
readl(hdm + CXL_HDM_DECODER0_BASE_HIGH_OFFSET(i)),
readl(hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(i)),
readl(hdm + CXL_HDM_DECODER0_SIZE_HIGH_OFFSET(i)),
readl(hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(i)));
if (FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl)) if (FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl))
return false; return false;
} }
...@@ -269,8 +277,11 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, ...@@ -269,8 +277,11 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
lockdep_assert_held_write(&cxl_dpa_rwsem); lockdep_assert_held_write(&cxl_dpa_rwsem);
if (!len) if (!len) {
goto success; dev_warn(dev, "decoder%d.%d: empty reservation attempted\n",
port->id, cxled->cxld.id);
return -EINVAL;
}
if (cxled->dpa_res) { if (cxled->dpa_res) {
dev_dbg(dev, "decoder%d.%d: existing allocation %pr assigned\n", dev_dbg(dev, "decoder%d.%d: existing allocation %pr assigned\n",
...@@ -323,7 +334,6 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, ...@@ -323,7 +334,6 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
cxled->mode = CXL_DECODER_MIXED; cxled->mode = CXL_DECODER_MIXED;
} }
success:
port->hdm_end++; port->hdm_end++;
get_device(&cxled->cxld.dev); get_device(&cxled->cxld.dev);
return 0; return 0;
...@@ -783,8 +793,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, ...@@ -783,8 +793,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
int *target_map, void __iomem *hdm, int which, int *target_map, void __iomem *hdm, int which,
u64 *dpa_base, struct cxl_endpoint_dvsec_info *info) u64 *dpa_base, struct cxl_endpoint_dvsec_info *info)
{ {
u64 size, base, skip, dpa_size, lo, hi;
struct cxl_endpoint_decoder *cxled; struct cxl_endpoint_decoder *cxled;
u64 size, base, skip, dpa_size;
bool committed; bool committed;
u32 remainder; u32 remainder;
int i, rc; int i, rc;
...@@ -799,8 +809,12 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, ...@@ -799,8 +809,12 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
which, info); which, info);
ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which)); ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which));
base = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(which)); lo = readl(hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(which));
size = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(which)); hi = readl(hdm + CXL_HDM_DECODER0_BASE_HIGH_OFFSET(which));
base = (hi << 32) + lo;
lo = readl(hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(which));
hi = readl(hdm + CXL_HDM_DECODER0_SIZE_HIGH_OFFSET(which));
size = (hi << 32) + lo;
committed = !!(ctrl & CXL_HDM_DECODER0_CTRL_COMMITTED); committed = !!(ctrl & CXL_HDM_DECODER0_CTRL_COMMITTED);
cxld->commit = cxl_decoder_commit; cxld->commit = cxl_decoder_commit;
cxld->reset = cxl_decoder_reset; cxld->reset = cxl_decoder_reset;
...@@ -833,6 +847,13 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, ...@@ -833,6 +847,13 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
port->id, cxld->id); port->id, cxld->id);
return -ENXIO; return -ENXIO;
} }
if (size == 0) {
dev_warn(&port->dev,
"decoder%d.%d: Committed with zero size\n",
port->id, cxld->id);
return -ENXIO;
}
port->commit_end = cxld->id; port->commit_end = cxld->id;
} else { } else {
/* unless / until type-2 drivers arrive, assume type-3 */ /* unless / until type-2 drivers arrive, assume type-3 */
...@@ -855,9 +876,14 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, ...@@ -855,9 +876,14 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
if (rc) if (rc)
return rc; return rc;
dev_dbg(&port->dev, "decoder%d.%d: range: %#llx-%#llx iw: %d ig: %d\n",
port->id, cxld->id, cxld->hpa_range.start, cxld->hpa_range.end,
cxld->interleave_ways, cxld->interleave_granularity);
if (!info) { if (!info) {
target_list.value = lo = readl(hdm + CXL_HDM_DECODER0_TL_LOW(which));
ioread64_hi_lo(hdm + CXL_HDM_DECODER0_TL_LOW(which)); hi = readl(hdm + CXL_HDM_DECODER0_TL_HIGH(which));
target_list.value = (hi << 32) + lo;
for (i = 0; i < cxld->interleave_ways; i++) for (i = 0; i < cxld->interleave_ways; i++)
target_map[i] = target_list.target_id[i]; target_map[i] = target_list.target_id[i];
...@@ -874,7 +900,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, ...@@ -874,7 +900,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
port->id, cxld->id, size, cxld->interleave_ways); port->id, cxld->id, size, cxld->interleave_ways);
return -ENXIO; return -ENXIO;
} }
skip = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_SKIP_LOW(which)); lo = readl(hdm + CXL_HDM_DECODER0_SKIP_LOW(which));
hi = readl(hdm + CXL_HDM_DECODER0_SKIP_HIGH(which));
skip = (hi << 32) + lo;
cxled = to_cxl_endpoint_decoder(&cxld->dev); cxled = to_cxl_endpoint_decoder(&cxld->dev);
rc = devm_cxl_dpa_reserve(cxled, *dpa_base + skip, dpa_size, skip); rc = devm_cxl_dpa_reserve(cxled, *dpa_base + skip, dpa_size, skip);
if (rc) { if (rc) {
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2020 Intel Corporation. All rights reserved. */ /* Copyright(c) 2020 Intel Corporation. All rights reserved. */
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/ktime.h> #include <linux/ktime.h>
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2020 Intel Corporation. All rights reserved. */ /* Copyright(c) 2020 Intel Corporation. All rights reserved. */
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/memregion.h> #include <linux/memregion.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
......
...@@ -66,14 +66,22 @@ static int cxl_switch_port_probe(struct cxl_port *port) ...@@ -66,14 +66,22 @@ static int cxl_switch_port_probe(struct cxl_port *port)
if (rc < 0) if (rc < 0)
return rc; return rc;
if (rc == 1)
return devm_cxl_add_passthrough_decoder(port);
cxlhdm = devm_cxl_setup_hdm(port, NULL); cxlhdm = devm_cxl_setup_hdm(port, NULL);
if (IS_ERR(cxlhdm)) if (!IS_ERR(cxlhdm))
return devm_cxl_enumerate_decoders(cxlhdm, NULL);
if (PTR_ERR(cxlhdm) != -ENODEV) {
dev_err(&port->dev, "Failed to map HDM decoder capability\n");
return PTR_ERR(cxlhdm); return PTR_ERR(cxlhdm);
}
if (rc == 1) {
dev_dbg(&port->dev, "Fallback to passthrough decoder\n");
return devm_cxl_add_passthrough_decoder(port);
}
return devm_cxl_enumerate_decoders(cxlhdm, NULL); dev_err(&port->dev, "HDM decoder capability not found\n");
return -ENXIO;
} }
static int cxl_endpoint_port_probe(struct cxl_port *port) static int cxl_endpoint_port_probe(struct cxl_port *port)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment