Lines Matching +full:rc +full:- +full:map +full:- +full:name

1 // SPDX-License-Identifier: GPL-2.0-only
3 #include <linux/io-64-nonatomic-lo-hi.h>
11 #include <linux/pci-doe.h>
28 * - Create the memX device and register on the CXL bus.
29 * - Enumerate device's register interface and map them.
30 * - Registers nvdimm bridge device with cxl_core.
31 * - Registers a CXL mailbox with cxl_core.
35 (readl((cxlds)->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET) & \
38 /* CXL 2.0 - 8.2.8.4 */
66 return -ETIMEDOUT; in cxl_pci_mbox_wait_for_doorbell()
71 dev_dbg(cxlds->dev, "Doorbell wait took %dms", in cxl_pci_mbox_wait_for_doorbell()
72 jiffies_to_msecs(end) - jiffies_to_msecs(start)); in cxl_pci_mbox_wait_for_doorbell()
79 status & CXLMDEV_FW_HALT ? " firmware-halt" : "")
83 (cmd)->opcode, \
85 status & CXLMDEV_FW_HALT ? " firmware-halt" : "")
88 * __cxl_pci_mbox_send_cmd() - Execute a mailbox command
93 * Return: -ETIMEDOUT if timeout occurred waiting for completion. 0 on success.
98 * registers defined by the mailbox capability ID - CXL 2.0 8.2.8.4. Memory
112 void __iomem *payload = cxlds->regs.mbox + CXLDEV_MBOX_PAYLOAD_OFFSET; in __cxl_pci_mbox_send_cmd()
113 struct device *dev = cxlds->dev; in __cxl_pci_mbox_send_cmd()
116 int rc; in __cxl_pci_mbox_send_cmd() local
118 lockdep_assert_held(&cxlds->mbox_mutex); in __cxl_pci_mbox_send_cmd()
124 * 3. Caller writes Command Payload Registers if input payload is non-empty in __cxl_pci_mbox_send_cmd()
129 * 8. If output payload is non-empty, host reads Command Payload Registers in __cxl_pci_mbox_send_cmd()
140 readq(cxlds->regs.memdev + CXLMDEV_STATUS_OFFSET); in __cxl_pci_mbox_send_cmd()
142 cxl_cmd_err(cxlds->dev, mbox_cmd, md_status, in __cxl_pci_mbox_send_cmd()
144 return -EBUSY; in __cxl_pci_mbox_send_cmd()
148 mbox_cmd->opcode); in __cxl_pci_mbox_send_cmd()
149 if (mbox_cmd->size_in) { in __cxl_pci_mbox_send_cmd()
150 if (WARN_ON(!mbox_cmd->payload_in)) in __cxl_pci_mbox_send_cmd()
151 return -EINVAL; in __cxl_pci_mbox_send_cmd()
154 mbox_cmd->size_in); in __cxl_pci_mbox_send_cmd()
155 memcpy_toio(payload, mbox_cmd->payload_in, mbox_cmd->size_in); in __cxl_pci_mbox_send_cmd()
159 writeq(cmd_reg, cxlds->regs.mbox + CXLDEV_MBOX_CMD_OFFSET); in __cxl_pci_mbox_send_cmd()
164 cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET); in __cxl_pci_mbox_send_cmd()
167 rc = cxl_pci_mbox_wait_for_doorbell(cxlds); in __cxl_pci_mbox_send_cmd()
168 if (rc == -ETIMEDOUT) { in __cxl_pci_mbox_send_cmd()
169 u64 md_status = readq(cxlds->regs.memdev + CXLMDEV_STATUS_OFFSET); in __cxl_pci_mbox_send_cmd()
171 cxl_cmd_err(cxlds->dev, mbox_cmd, md_status, "mailbox timeout"); in __cxl_pci_mbox_send_cmd()
172 return rc; in __cxl_pci_mbox_send_cmd()
176 status_reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_STATUS_OFFSET); in __cxl_pci_mbox_send_cmd()
177 mbox_cmd->return_code = in __cxl_pci_mbox_send_cmd()
180 if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS) { in __cxl_pci_mbox_send_cmd()
187 cmd_reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_CMD_OFFSET); in __cxl_pci_mbox_send_cmd()
191 if (out_len && mbox_cmd->payload_out) { in __cxl_pci_mbox_send_cmd()
199 size_t n = min3(mbox_cmd->size_out, cxlds->payload_size, out_len); in __cxl_pci_mbox_send_cmd()
201 memcpy_fromio(mbox_cmd->payload_out, payload, n); in __cxl_pci_mbox_send_cmd()
202 mbox_cmd->size_out = n; in __cxl_pci_mbox_send_cmd()
204 mbox_cmd->size_out = 0; in __cxl_pci_mbox_send_cmd()
212 int rc; in cxl_pci_mbox_send() local
214 mutex_lock_io(&cxlds->mbox_mutex); in cxl_pci_mbox_send()
215 rc = __cxl_pci_mbox_send_cmd(cxlds, cmd); in cxl_pci_mbox_send()
216 mutex_unlock(&cxlds->mbox_mutex); in cxl_pci_mbox_send()
218 return rc; in cxl_pci_mbox_send()
223 const int cap = readl(cxlds->regs.mbox + CXLDEV_MBOX_CAPS_OFFSET); in cxl_pci_setup_mailbox()
229 md_status = readq(cxlds->regs.memdev + CXLMDEV_STATUS_OFFSET); in cxl_pci_setup_mailbox()
237 cxl_err(cxlds->dev, md_status, in cxl_pci_setup_mailbox()
239 return -ETIMEDOUT; in cxl_pci_setup_mailbox()
249 cxl_err(cxlds->dev, md_status, "timeout awaiting mailbox idle"); in cxl_pci_setup_mailbox()
250 return -ETIMEDOUT; in cxl_pci_setup_mailbox()
253 cxlds->mbox_send = cxl_pci_mbox_send; in cxl_pci_setup_mailbox()
254 cxlds->payload_size = in cxl_pci_setup_mailbox()
264 cxlds->payload_size = min_t(size_t, cxlds->payload_size, SZ_1M); in cxl_pci_setup_mailbox()
265 if (cxlds->payload_size < 256) { in cxl_pci_setup_mailbox()
266 dev_err(cxlds->dev, "Mailbox is too small (%zub)", in cxl_pci_setup_mailbox()
267 cxlds->payload_size); in cxl_pci_setup_mailbox()
268 return -ENXIO; in cxl_pci_setup_mailbox()
271 dev_dbg(cxlds->dev, "Mailbox payload sized %zu", in cxl_pci_setup_mailbox()
272 cxlds->payload_size); in cxl_pci_setup_mailbox()
277 static int cxl_map_regblock(struct pci_dev *pdev, struct cxl_register_map *map) in cxl_map_regblock() argument
280 int bar = map->barno; in cxl_map_regblock()
281 struct device *dev = &pdev->dev; in cxl_map_regblock()
282 resource_size_t offset = map->block_offset; in cxl_map_regblock()
287 &pdev->resource[bar], &offset); in cxl_map_regblock()
288 return -ENXIO; in cxl_map_regblock()
293 dev_err(dev, "failed to map registers\n"); in cxl_map_regblock()
294 return -ENOMEM; in cxl_map_regblock()
300 map->base = addr + map->block_offset; in cxl_map_regblock()
305 struct cxl_register_map *map) in cxl_unmap_regblock() argument
307 pci_iounmap(pdev, map->base - map->block_offset); in cxl_unmap_regblock()
308 map->base = NULL; in cxl_unmap_regblock()
311 static int cxl_probe_regs(struct pci_dev *pdev, struct cxl_register_map *map) in cxl_probe_regs() argument
315 struct device *dev = &pdev->dev; in cxl_probe_regs()
316 void __iomem *base = map->base; in cxl_probe_regs()
318 switch (map->reg_type) { in cxl_probe_regs()
320 comp_map = &map->component_map; in cxl_probe_regs()
322 if (!comp_map->hdm_decoder.valid) { in cxl_probe_regs()
324 return -ENXIO; in cxl_probe_regs()
330 dev_map = &map->device_map; in cxl_probe_regs()
332 if (!dev_map->status.valid || !dev_map->mbox.valid || in cxl_probe_regs()
333 !dev_map->memdev.valid) { in cxl_probe_regs()
335 !dev_map->status.valid ? "status " : "", in cxl_probe_regs()
336 !dev_map->mbox.valid ? "mbox " : "", in cxl_probe_regs()
337 !dev_map->memdev.valid ? "memdev " : ""); in cxl_probe_regs()
338 return -ENXIO; in cxl_probe_regs()
350 static int cxl_map_regs(struct cxl_dev_state *cxlds, struct cxl_register_map *map) in cxl_map_regs() argument
352 struct device *dev = cxlds->dev; in cxl_map_regs()
355 switch (map->reg_type) { in cxl_map_regs()
357 cxl_map_component_regs(pdev, &cxlds->regs.component, map); in cxl_map_regs()
361 cxl_map_device_regs(pdev, &cxlds->regs.device_regs, map); in cxl_map_regs()
372 struct cxl_register_map *map) in cxl_setup_regs() argument
374 int rc; in cxl_setup_regs() local
376 rc = cxl_find_regblock(pdev, type, map); in cxl_setup_regs()
377 if (rc) in cxl_setup_regs()
378 return rc; in cxl_setup_regs()
380 rc = cxl_map_regblock(pdev, map); in cxl_setup_regs()
381 if (rc) in cxl_setup_regs()
382 return rc; in cxl_setup_regs()
384 rc = cxl_probe_regs(pdev, map); in cxl_setup_regs()
385 cxl_unmap_regblock(pdev, map); in cxl_setup_regs()
387 return rc; in cxl_setup_regs()
397 struct device *dev = cxlds->dev; in devm_cxl_pci_create_doe()
401 xa_init(&cxlds->doe_mbs); in devm_cxl_pci_create_doe()
402 if (devm_add_action(&pdev->dev, cxl_pci_destroy_doe, &cxlds->doe_mbs)) { in devm_cxl_pci_create_doe()
421 if (xa_insert(&cxlds->doe_mbs, off, doe_mb, GFP_KERNEL)) { in devm_cxl_pci_create_doe()
433 struct cxl_register_map map; in cxl_pci_probe() local
436 int rc; in cxl_pci_probe() local
445 rc = pcim_enable_device(pdev); in cxl_pci_probe()
446 if (rc) in cxl_pci_probe()
447 return rc; in cxl_pci_probe()
449 cxlds = cxl_dev_state_create(&pdev->dev); in cxl_pci_probe()
453 cxlds->serial = pci_get_dsn(pdev); in cxl_pci_probe()
454 cxlds->cxl_dvsec = pci_find_dvsec_capability( in cxl_pci_probe()
456 if (!cxlds->cxl_dvsec) in cxl_pci_probe()
457 dev_warn(&pdev->dev, in cxl_pci_probe()
460 rc = cxl_setup_regs(pdev, CXL_REGLOC_RBI_MEMDEV, &map); in cxl_pci_probe()
461 if (rc) in cxl_pci_probe()
462 return rc; in cxl_pci_probe()
464 rc = cxl_map_regs(cxlds, &map); in cxl_pci_probe()
465 if (rc) in cxl_pci_probe()
466 return rc; in cxl_pci_probe()
472 cxlds->component_reg_phys = CXL_RESOURCE_NONE; in cxl_pci_probe()
473 rc = cxl_setup_regs(pdev, CXL_REGLOC_RBI_COMPONENT, &map); in cxl_pci_probe()
474 if (rc) in cxl_pci_probe()
475 dev_warn(&pdev->dev, "No component registers (%d)\n", rc); in cxl_pci_probe()
477 cxlds->component_reg_phys = cxl_regmap_to_base(pdev, &map); in cxl_pci_probe()
481 rc = cxl_pci_setup_mailbox(cxlds); in cxl_pci_probe()
482 if (rc) in cxl_pci_probe()
483 return rc; in cxl_pci_probe()
485 rc = cxl_enumerate_cmds(cxlds); in cxl_pci_probe()
486 if (rc) in cxl_pci_probe()
487 return rc; in cxl_pci_probe()
489 rc = cxl_dev_state_identify(cxlds); in cxl_pci_probe()
490 if (rc) in cxl_pci_probe()
491 return rc; in cxl_pci_probe()
493 rc = cxl_mem_create_range_info(cxlds); in cxl_pci_probe()
494 if (rc) in cxl_pci_probe()
495 return rc; in cxl_pci_probe()
501 if (resource_size(&cxlds->pmem_res) && IS_ENABLED(CONFIG_CXL_PMEM)) in cxl_pci_probe()
502 rc = devm_cxl_add_nvdimm(&pdev->dev, cxlmd); in cxl_pci_probe()
504 return rc; in cxl_pci_probe()
508 /* PCI class code for CXL.mem Type-3 Devices */
515 .name = KBUILD_MODNAME,