Loading drivers/cxl/core/cdat.c +3 −3 Original line number Diff line number Diff line Loading @@ -336,7 +336,7 @@ static int match_cxlrd_hb(struct device *dev, void *data) cxlrd = to_cxl_root_decoder(dev); cxlsd = &cxlrd->cxlsd; guard(rwsem_read)(&cxl_region_rwsem); guard(rwsem_read)(&cxl_rwsem.region); for (int i = 0; i < cxlsd->nr_targets; i++) { if (host_bridge == cxlsd->target[i]->dport_dev) return 1; Loading Loading @@ -987,7 +987,7 @@ void cxl_region_shared_upstream_bandwidth_update(struct cxl_region *cxlr) bool is_root; int rc; lockdep_assert_held(&cxl_dpa_rwsem); lockdep_assert_held(&cxl_rwsem.dpa); struct xarray *usp_xa __free(free_perf_xa) = kzalloc(sizeof(*usp_xa), GFP_KERNEL); Loading Loading @@ -1057,7 +1057,7 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr, { struct cxl_dpa_perf *perf; lockdep_assert_held(&cxl_dpa_rwsem); lockdep_assert_held(&cxl_rwsem.dpa); perf = cxled_get_dpa_perf(cxled); if (IS_ERR(perf)) Loading drivers/cxl/core/core.h +28 −4 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ #define __CXL_CORE_H__ #include <cxl/mailbox.h> #include <linux/rwsem.h> extern const struct device_type cxl_nvdimm_bridge_type; extern const struct device_type cxl_nvdimm_type; Loading @@ -12,6 +13,11 @@ extern const struct device_type cxl_pmu_type; extern struct attribute_group cxl_base_attribute_group; enum cxl_detach_mode { DETACH_ONLY, DETACH_INVALIDATE, }; #ifdef CONFIG_CXL_REGION extern struct device_attribute dev_attr_create_pmem_region; extern struct device_attribute dev_attr_create_ram_region; Loading @@ -20,7 +26,11 @@ extern struct device_attribute dev_attr_region; extern const struct device_type cxl_pmem_region_type; extern const struct device_type cxl_dax_region_type; extern const struct device_type cxl_region_type; void cxl_decoder_kill_region(struct cxl_endpoint_decoder *cxled); int cxl_decoder_detach(struct cxl_region *cxlr, struct cxl_endpoint_decoder *cxled, int pos, enum cxl_detach_mode mode); #define CXL_REGION_ATTR(x) (&dev_attr_##x.attr) #define CXL_REGION_TYPE(x) (&cxl_region_type) #define SET_CXL_REGION_ATTR(x) (&dev_attr_##x.attr), Loading Loading @@ -48,7 +58,9 @@ static inline int cxl_get_poison_by_endpoint(struct cxl_port *port) { return 0; } static inline void cxl_decoder_kill_region(struct cxl_endpoint_decoder *cxled) static inline int cxl_decoder_detach(struct cxl_region *cxlr, struct cxl_endpoint_decoder *cxled, int pos, enum cxl_detach_mode mode) { } static inline int cxl_region_init(void) Loading Loading @@ -97,8 +109,20 @@ u16 cxl_rcrb_to_aer(struct device *dev, resource_size_t rcrb); #define PCI_RCRB_CAP_HDR_NEXT_MASK GENMASK(15, 8) #define PCI_CAP_EXP_SIZEOF 0x3c extern struct rw_semaphore cxl_dpa_rwsem; extern struct rw_semaphore cxl_region_rwsem; struct cxl_rwsem { /* * All changes to HPA (interleave configuration) occur with this * lock held for write. */ struct rw_semaphore region; /* * All changes to a device DPA space occur with this lock held * for write. */ struct rw_semaphore dpa; }; extern struct cxl_rwsem cxl_rwsem; int cxl_memdev_init(void); void cxl_memdev_exit(void); Loading drivers/cxl/core/edac.c +20 −24 Original line number Diff line number Diff line Loading @@ -115,10 +115,9 @@ static int cxl_scrub_get_attrbs(struct cxl_patrol_scrub_context *cxl_ps_ctx, flags, min_cycle); } struct rw_semaphore *region_lock __free(rwsem_read_release) = rwsem_read_intr_acquire(&cxl_region_rwsem); if (!region_lock) return -EINTR; ACQUIRE(rwsem_read_intr, rwsem)(&cxl_rwsem.region); if ((ret = ACQUIRE_ERR(rwsem_read_intr, &rwsem))) return ret; cxlr = cxl_ps_ctx->cxlr; p = &cxlr->params; Loading Loading @@ -158,10 +157,9 @@ static int cxl_scrub_set_attrbs_region(struct device *dev, struct cxl_region *cxlr; int ret, i; struct rw_semaphore *region_lock __free(rwsem_read_release) = rwsem_read_intr_acquire(&cxl_region_rwsem); if (!region_lock) return -EINTR; ACQUIRE(rwsem_read_intr, rwsem)(&cxl_rwsem.region); if ((ret = ACQUIRE_ERR(rwsem_read_intr, &rwsem))) return ret; cxlr = cxl_ps_ctx->cxlr; p = &cxlr->params; Loading Loading @@ -1340,16 +1338,15 @@ cxl_mem_perform_sparing(struct device *dev, struct cxl_memdev_sparing_in_payload sparing_pi; struct cxl_event_dram *rec = NULL; u16 validity_flags = 0; int ret; struct rw_semaphore *region_lock __free(rwsem_read_release) = rwsem_read_intr_acquire(&cxl_region_rwsem); if (!region_lock) return -EINTR; ACQUIRE(rwsem_read_intr, region_rwsem)(&cxl_rwsem.region); if ((ret = ACQUIRE_ERR(rwsem_read_intr, ®ion_rwsem))) return ret; struct rw_semaphore *dpa_lock __free(rwsem_read_release) = rwsem_read_intr_acquire(&cxl_dpa_rwsem); if (!dpa_lock) return -EINTR; ACQUIRE(rwsem_read_intr, dpa_rwsem)(&cxl_rwsem.dpa); if ((ret = ACQUIRE_ERR(rwsem_read_intr, &dpa_rwsem))) return ret; if (!cxl_sparing_ctx->cap_safe_when_in_use) { /* Memory to repair must be offline */ Loading Loading @@ -1787,16 +1784,15 @@ static int cxl_mem_perform_ppr(struct cxl_ppr_context *cxl_ppr_ctx) struct cxl_memdev_ppr_maintenance_attrbs maintenance_attrbs; struct cxl_memdev *cxlmd = cxl_ppr_ctx->cxlmd; struct cxl_mem_repair_attrbs attrbs = { 0 }; int ret; struct rw_semaphore *region_lock __free(rwsem_read_release) = rwsem_read_intr_acquire(&cxl_region_rwsem); if (!region_lock) return -EINTR; ACQUIRE(rwsem_read_intr, region_rwsem)(&cxl_rwsem.region); if ((ret = ACQUIRE_ERR(rwsem_read_intr, ®ion_rwsem))) return ret; struct rw_semaphore *dpa_lock __free(rwsem_read_release) = rwsem_read_intr_acquire(&cxl_dpa_rwsem); if (!dpa_lock) return -EINTR; ACQUIRE(rwsem_read_intr, dpa_rwsem)(&cxl_rwsem.dpa); if ((ret = ACQUIRE_ERR(rwsem_read_intr, &dpa_rwsem))) return ret; if (!cxl_ppr_ctx->media_accessible || !cxl_ppr_ctx->data_retained) { /* Memory to repair must be offline */ Loading drivers/cxl/core/hdm.c +62 −56 Original line number Diff line number Diff line Loading @@ -16,7 +16,10 @@ * for enumerating these registers and capabilities. */ DECLARE_RWSEM(cxl_dpa_rwsem); struct cxl_rwsem cxl_rwsem = { .region = __RWSEM_INITIALIZER(cxl_rwsem.region), .dpa = __RWSEM_INITIALIZER(cxl_rwsem.dpa), }; static int add_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, int *target_map) Loading Loading @@ -214,7 +217,7 @@ void cxl_dpa_debug(struct seq_file *file, struct cxl_dev_state *cxlds) { struct resource *p1, *p2; guard(rwsem_read)(&cxl_dpa_rwsem); guard(rwsem_read)(&cxl_rwsem.dpa); for (p1 = cxlds->dpa_res.child; p1; p1 = p1->sibling) { __cxl_dpa_debug(file, p1, 0); for (p2 = p1->child; p2; p2 = p2->sibling) Loading Loading @@ -266,7 +269,7 @@ static void __cxl_dpa_release(struct cxl_endpoint_decoder *cxled) struct resource *res = cxled->dpa_res; resource_size_t skip_start; lockdep_assert_held_write(&cxl_dpa_rwsem); lockdep_assert_held_write(&cxl_rwsem.dpa); /* save @skip_start, before @res is released */ skip_start = res->start - cxled->skip; Loading @@ -281,7 +284,7 @@ static void __cxl_dpa_release(struct cxl_endpoint_decoder *cxled) static void cxl_dpa_release(void *cxled) { guard(rwsem_write)(&cxl_dpa_rwsem); guard(rwsem_write)(&cxl_rwsem.dpa); __cxl_dpa_release(cxled); } Loading @@ -293,7 +296,7 @@ static void devm_cxl_dpa_release(struct cxl_endpoint_decoder *cxled) { struct cxl_port *port = cxled_to_port(cxled); lockdep_assert_held_write(&cxl_dpa_rwsem); lockdep_assert_held_write(&cxl_rwsem.dpa); devm_remove_action(&port->dev, cxl_dpa_release, cxled); __cxl_dpa_release(cxled); } Loading Loading @@ -361,7 +364,7 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, struct resource *res; int rc; lockdep_assert_held_write(&cxl_dpa_rwsem); lockdep_assert_held_write(&cxl_rwsem.dpa); if (!len) { dev_warn(dev, "decoder%d.%d: empty reservation attempted\n", Loading Loading @@ -470,7 +473,7 @@ int cxl_dpa_setup(struct cxl_dev_state *cxlds, const struct cxl_dpa_info *info) { struct device *dev = cxlds->dev; guard(rwsem_write)(&cxl_dpa_rwsem); guard(rwsem_write)(&cxl_rwsem.dpa); if (cxlds->nr_partitions) return -EBUSY; Loading Loading @@ -516,9 +519,8 @@ int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, struct cxl_port *port = cxled_to_port(cxled); int rc; down_write(&cxl_dpa_rwsem); scoped_guard(rwsem_write, &cxl_rwsem.dpa) rc = __cxl_dpa_reserve(cxled, base, len, skipped); up_write(&cxl_dpa_rwsem); if (rc) return rc; Loading @@ -529,7 +531,7 @@ EXPORT_SYMBOL_NS_GPL(devm_cxl_dpa_reserve, "CXL"); resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled) { guard(rwsem_read)(&cxl_dpa_rwsem); guard(rwsem_read)(&cxl_rwsem.dpa); if (cxled->dpa_res) return resource_size(cxled->dpa_res); Loading @@ -540,7 +542,7 @@ resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled) { resource_size_t base = -1; lockdep_assert_held(&cxl_dpa_rwsem); lockdep_assert_held(&cxl_rwsem.dpa); if (cxled->dpa_res) base = cxled->dpa_res->start; Loading @@ -559,7 +561,7 @@ int cxl_dpa_free(struct cxl_endpoint_decoder *cxled) struct cxl_port *port = cxled_to_port(cxled); struct device *dev = &cxled->cxld.dev; guard(rwsem_write)(&cxl_dpa_rwsem); guard(rwsem_write)(&cxl_rwsem.dpa); if (!cxled->dpa_res) return 0; if (cxled->cxld.region) { Loading Loading @@ -589,7 +591,7 @@ int cxl_dpa_set_part(struct cxl_endpoint_decoder *cxled, struct device *dev = &cxled->cxld.dev; int part; guard(rwsem_write)(&cxl_dpa_rwsem); guard(rwsem_write)(&cxl_rwsem.dpa); if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) return -EBUSY; Loading Loading @@ -621,7 +623,7 @@ static int __cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, u64 size) struct resource *p, *last; int part; guard(rwsem_write)(&cxl_dpa_rwsem); guard(rwsem_write)(&cxl_rwsem.dpa); if (cxled->cxld.region) { dev_dbg(dev, "decoder attached to %s\n", dev_name(&cxled->cxld.region->dev)); Loading Loading @@ -771,46 +773,12 @@ static int cxld_await_commit(void __iomem *hdm, int id) return -ETIMEDOUT; } static int cxl_decoder_commit(struct cxl_decoder *cxld) static void setup_hw_decoder(struct cxl_decoder *cxld, void __iomem *hdm) { struct cxl_port *port = to_cxl_port(cxld->dev.parent); struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev); void __iomem *hdm = cxlhdm->regs.hdm_decoder; int id = cxld->id, rc; int id = cxld->id; u64 base, size; u32 ctrl; if (cxld->flags & CXL_DECODER_F_ENABLE) return 0; if (cxl_num_decoders_committed(port) != id) { dev_dbg(&port->dev, "%s: out of order commit, expected decoder%d.%d\n", dev_name(&cxld->dev), port->id, cxl_num_decoders_committed(port)); return -EBUSY; } /* * For endpoint decoders hosted on CXL memory devices that * support the sanitize operation, make sure sanitize is not in-flight. */ if (is_endpoint_decoder(&cxld->dev)) { struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(&cxld->dev); struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); if (mds && mds->security.sanitize_active) { dev_dbg(&cxlmd->dev, "attempted to commit %s during sanitize\n", dev_name(&cxld->dev)); return -EBUSY; } } down_read(&cxl_dpa_rwsem); /* common decoder settings */ ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(cxld->id)); cxld_set_interleave(cxld, &ctrl); Loading Loading @@ -844,7 +812,47 @@ static int cxl_decoder_commit(struct cxl_decoder *cxld) } writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id)); up_read(&cxl_dpa_rwsem); } static int cxl_decoder_commit(struct cxl_decoder *cxld) { struct cxl_port *port = to_cxl_port(cxld->dev.parent); struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev); void __iomem *hdm = cxlhdm->regs.hdm_decoder; int id = cxld->id, rc; if (cxld->flags & CXL_DECODER_F_ENABLE) return 0; if (cxl_num_decoders_committed(port) != id) { dev_dbg(&port->dev, "%s: out of order commit, expected decoder%d.%d\n", dev_name(&cxld->dev), port->id, cxl_num_decoders_committed(port)); return -EBUSY; } /* * For endpoint decoders hosted on CXL memory devices that * support the sanitize operation, make sure sanitize is not in-flight. */ if (is_endpoint_decoder(&cxld->dev)) { struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(&cxld->dev); struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); if (mds && mds->security.sanitize_active) { dev_dbg(&cxlmd->dev, "attempted to commit %s during sanitize\n", dev_name(&cxld->dev)); return -EBUSY; } } scoped_guard(rwsem_read, &cxl_rwsem.dpa) setup_hw_decoder(cxld, hdm); port->commit_end++; rc = cxld_await_commit(hdm, cxld->id); Loading Loading @@ -882,7 +890,7 @@ void cxl_port_commit_reap(struct cxl_decoder *cxld) { struct cxl_port *port = to_cxl_port(cxld->dev.parent); lockdep_assert_held_write(&cxl_region_rwsem); lockdep_assert_held_write(&cxl_rwsem.region); /* * Once the highest committed decoder is disabled, free any other Loading Loading @@ -914,7 +922,6 @@ static void cxl_decoder_reset(struct cxl_decoder *cxld) "%s: out of order reset, expected decoder%d.%d\n", dev_name(&cxld->dev), port->id, port->commit_end); down_read(&cxl_dpa_rwsem); ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id)); ctrl &= ~CXL_HDM_DECODER0_CTRL_COMMIT; writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id)); Loading @@ -923,7 +930,6 @@ static void cxl_decoder_reset(struct cxl_decoder *cxld) writel(0, hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(id)); writel(0, hdm + CXL_HDM_DECODER0_BASE_HIGH_OFFSET(id)); writel(0, hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(id)); up_read(&cxl_dpa_rwsem); cxld->flags &= ~CXL_DECODER_F_ENABLE; Loading Loading @@ -1032,7 +1038,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, else cxld->target_type = CXL_DECODER_DEVMEM; guard(rwsem_write)(&cxl_region_rwsem); guard(rwsem_write)(&cxl_rwsem.region); if (cxld->id != cxl_num_decoders_committed(port)) { dev_warn(&port->dev, "decoder%d.%d: Committed out of order\n", Loading drivers/cxl/core/mbox.c +6 −7 Original line number Diff line number Diff line Loading @@ -909,8 +909,8 @@ void cxl_event_trace_record(const struct cxl_memdev *cxlmd, * translations. Take topology mutation locks and lookup * { HPA, REGION } from { DPA, MEMDEV } in the event record. */ guard(rwsem_read)(&cxl_region_rwsem); guard(rwsem_read)(&cxl_dpa_rwsem); guard(rwsem_read)(&cxl_rwsem.region); guard(rwsem_read)(&cxl_rwsem.dpa); dpa = le64_to_cpu(evt->media_hdr.phys_addr) & CXL_DPA_MASK; cxlr = cxl_dpa_to_region(cxlmd, dpa); Loading Loading @@ -1265,7 +1265,7 @@ int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd) /* synchronize with cxl_mem_probe() and decoder write operations */ guard(device)(&cxlmd->dev); endpoint = cxlmd->endpoint; guard(rwsem_read)(&cxl_region_rwsem); guard(rwsem_read)(&cxl_rwsem.region); /* * Require an endpoint to be safe otherwise the driver can not * be sure that the device is unmapped. Loading Loading @@ -1401,8 +1401,8 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, int nr_records = 0; int rc; rc = mutex_lock_interruptible(&mds->poison.lock); if (rc) ACQUIRE(mutex_intr, lock)(&mds->poison.mutex); if ((rc = ACQUIRE_ERR(mutex_intr, &lock))) return rc; po = mds->poison.list_out; Loading Loading @@ -1437,7 +1437,6 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, } } while (po->flags & CXL_POISON_FLAG_MORE); mutex_unlock(&mds->poison.lock); return rc; } EXPORT_SYMBOL_NS_GPL(cxl_mem_get_poison, "CXL"); Loading Loading @@ -1473,7 +1472,7 @@ int cxl_poison_state_init(struct cxl_memdev_state *mds) return rc; } mutex_init(&mds->poison.lock); mutex_init(&mds->poison.mutex); return 0; } EXPORT_SYMBOL_NS_GPL(cxl_poison_state_init, "CXL"); Loading Loading
drivers/cxl/core/cdat.c +3 −3 Original line number Diff line number Diff line Loading @@ -336,7 +336,7 @@ static int match_cxlrd_hb(struct device *dev, void *data) cxlrd = to_cxl_root_decoder(dev); cxlsd = &cxlrd->cxlsd; guard(rwsem_read)(&cxl_region_rwsem); guard(rwsem_read)(&cxl_rwsem.region); for (int i = 0; i < cxlsd->nr_targets; i++) { if (host_bridge == cxlsd->target[i]->dport_dev) return 1; Loading Loading @@ -987,7 +987,7 @@ void cxl_region_shared_upstream_bandwidth_update(struct cxl_region *cxlr) bool is_root; int rc; lockdep_assert_held(&cxl_dpa_rwsem); lockdep_assert_held(&cxl_rwsem.dpa); struct xarray *usp_xa __free(free_perf_xa) = kzalloc(sizeof(*usp_xa), GFP_KERNEL); Loading Loading @@ -1057,7 +1057,7 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr, { struct cxl_dpa_perf *perf; lockdep_assert_held(&cxl_dpa_rwsem); lockdep_assert_held(&cxl_rwsem.dpa); perf = cxled_get_dpa_perf(cxled); if (IS_ERR(perf)) Loading
drivers/cxl/core/core.h +28 −4 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ #define __CXL_CORE_H__ #include <cxl/mailbox.h> #include <linux/rwsem.h> extern const struct device_type cxl_nvdimm_bridge_type; extern const struct device_type cxl_nvdimm_type; Loading @@ -12,6 +13,11 @@ extern const struct device_type cxl_pmu_type; extern struct attribute_group cxl_base_attribute_group; enum cxl_detach_mode { DETACH_ONLY, DETACH_INVALIDATE, }; #ifdef CONFIG_CXL_REGION extern struct device_attribute dev_attr_create_pmem_region; extern struct device_attribute dev_attr_create_ram_region; Loading @@ -20,7 +26,11 @@ extern struct device_attribute dev_attr_region; extern const struct device_type cxl_pmem_region_type; extern const struct device_type cxl_dax_region_type; extern const struct device_type cxl_region_type; void cxl_decoder_kill_region(struct cxl_endpoint_decoder *cxled); int cxl_decoder_detach(struct cxl_region *cxlr, struct cxl_endpoint_decoder *cxled, int pos, enum cxl_detach_mode mode); #define CXL_REGION_ATTR(x) (&dev_attr_##x.attr) #define CXL_REGION_TYPE(x) (&cxl_region_type) #define SET_CXL_REGION_ATTR(x) (&dev_attr_##x.attr), Loading Loading @@ -48,7 +58,9 @@ static inline int cxl_get_poison_by_endpoint(struct cxl_port *port) { return 0; } static inline void cxl_decoder_kill_region(struct cxl_endpoint_decoder *cxled) static inline int cxl_decoder_detach(struct cxl_region *cxlr, struct cxl_endpoint_decoder *cxled, int pos, enum cxl_detach_mode mode) { } static inline int cxl_region_init(void) Loading Loading @@ -97,8 +109,20 @@ u16 cxl_rcrb_to_aer(struct device *dev, resource_size_t rcrb); #define PCI_RCRB_CAP_HDR_NEXT_MASK GENMASK(15, 8) #define PCI_CAP_EXP_SIZEOF 0x3c extern struct rw_semaphore cxl_dpa_rwsem; extern struct rw_semaphore cxl_region_rwsem; struct cxl_rwsem { /* * All changes to HPA (interleave configuration) occur with this * lock held for write. */ struct rw_semaphore region; /* * All changes to a device DPA space occur with this lock held * for write. */ struct rw_semaphore dpa; }; extern struct cxl_rwsem cxl_rwsem; int cxl_memdev_init(void); void cxl_memdev_exit(void); Loading
drivers/cxl/core/edac.c +20 −24 Original line number Diff line number Diff line Loading @@ -115,10 +115,9 @@ static int cxl_scrub_get_attrbs(struct cxl_patrol_scrub_context *cxl_ps_ctx, flags, min_cycle); } struct rw_semaphore *region_lock __free(rwsem_read_release) = rwsem_read_intr_acquire(&cxl_region_rwsem); if (!region_lock) return -EINTR; ACQUIRE(rwsem_read_intr, rwsem)(&cxl_rwsem.region); if ((ret = ACQUIRE_ERR(rwsem_read_intr, &rwsem))) return ret; cxlr = cxl_ps_ctx->cxlr; p = &cxlr->params; Loading Loading @@ -158,10 +157,9 @@ static int cxl_scrub_set_attrbs_region(struct device *dev, struct cxl_region *cxlr; int ret, i; struct rw_semaphore *region_lock __free(rwsem_read_release) = rwsem_read_intr_acquire(&cxl_region_rwsem); if (!region_lock) return -EINTR; ACQUIRE(rwsem_read_intr, rwsem)(&cxl_rwsem.region); if ((ret = ACQUIRE_ERR(rwsem_read_intr, &rwsem))) return ret; cxlr = cxl_ps_ctx->cxlr; p = &cxlr->params; Loading Loading @@ -1340,16 +1338,15 @@ cxl_mem_perform_sparing(struct device *dev, struct cxl_memdev_sparing_in_payload sparing_pi; struct cxl_event_dram *rec = NULL; u16 validity_flags = 0; int ret; struct rw_semaphore *region_lock __free(rwsem_read_release) = rwsem_read_intr_acquire(&cxl_region_rwsem); if (!region_lock) return -EINTR; ACQUIRE(rwsem_read_intr, region_rwsem)(&cxl_rwsem.region); if ((ret = ACQUIRE_ERR(rwsem_read_intr, ®ion_rwsem))) return ret; struct rw_semaphore *dpa_lock __free(rwsem_read_release) = rwsem_read_intr_acquire(&cxl_dpa_rwsem); if (!dpa_lock) return -EINTR; ACQUIRE(rwsem_read_intr, dpa_rwsem)(&cxl_rwsem.dpa); if ((ret = ACQUIRE_ERR(rwsem_read_intr, &dpa_rwsem))) return ret; if (!cxl_sparing_ctx->cap_safe_when_in_use) { /* Memory to repair must be offline */ Loading Loading @@ -1787,16 +1784,15 @@ static int cxl_mem_perform_ppr(struct cxl_ppr_context *cxl_ppr_ctx) struct cxl_memdev_ppr_maintenance_attrbs maintenance_attrbs; struct cxl_memdev *cxlmd = cxl_ppr_ctx->cxlmd; struct cxl_mem_repair_attrbs attrbs = { 0 }; int ret; struct rw_semaphore *region_lock __free(rwsem_read_release) = rwsem_read_intr_acquire(&cxl_region_rwsem); if (!region_lock) return -EINTR; ACQUIRE(rwsem_read_intr, region_rwsem)(&cxl_rwsem.region); if ((ret = ACQUIRE_ERR(rwsem_read_intr, ®ion_rwsem))) return ret; struct rw_semaphore *dpa_lock __free(rwsem_read_release) = rwsem_read_intr_acquire(&cxl_dpa_rwsem); if (!dpa_lock) return -EINTR; ACQUIRE(rwsem_read_intr, dpa_rwsem)(&cxl_rwsem.dpa); if ((ret = ACQUIRE_ERR(rwsem_read_intr, &dpa_rwsem))) return ret; if (!cxl_ppr_ctx->media_accessible || !cxl_ppr_ctx->data_retained) { /* Memory to repair must be offline */ Loading
drivers/cxl/core/hdm.c +62 −56 Original line number Diff line number Diff line Loading @@ -16,7 +16,10 @@ * for enumerating these registers and capabilities. */ DECLARE_RWSEM(cxl_dpa_rwsem); struct cxl_rwsem cxl_rwsem = { .region = __RWSEM_INITIALIZER(cxl_rwsem.region), .dpa = __RWSEM_INITIALIZER(cxl_rwsem.dpa), }; static int add_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, int *target_map) Loading Loading @@ -214,7 +217,7 @@ void cxl_dpa_debug(struct seq_file *file, struct cxl_dev_state *cxlds) { struct resource *p1, *p2; guard(rwsem_read)(&cxl_dpa_rwsem); guard(rwsem_read)(&cxl_rwsem.dpa); for (p1 = cxlds->dpa_res.child; p1; p1 = p1->sibling) { __cxl_dpa_debug(file, p1, 0); for (p2 = p1->child; p2; p2 = p2->sibling) Loading Loading @@ -266,7 +269,7 @@ static void __cxl_dpa_release(struct cxl_endpoint_decoder *cxled) struct resource *res = cxled->dpa_res; resource_size_t skip_start; lockdep_assert_held_write(&cxl_dpa_rwsem); lockdep_assert_held_write(&cxl_rwsem.dpa); /* save @skip_start, before @res is released */ skip_start = res->start - cxled->skip; Loading @@ -281,7 +284,7 @@ static void __cxl_dpa_release(struct cxl_endpoint_decoder *cxled) static void cxl_dpa_release(void *cxled) { guard(rwsem_write)(&cxl_dpa_rwsem); guard(rwsem_write)(&cxl_rwsem.dpa); __cxl_dpa_release(cxled); } Loading @@ -293,7 +296,7 @@ static void devm_cxl_dpa_release(struct cxl_endpoint_decoder *cxled) { struct cxl_port *port = cxled_to_port(cxled); lockdep_assert_held_write(&cxl_dpa_rwsem); lockdep_assert_held_write(&cxl_rwsem.dpa); devm_remove_action(&port->dev, cxl_dpa_release, cxled); __cxl_dpa_release(cxled); } Loading Loading @@ -361,7 +364,7 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, struct resource *res; int rc; lockdep_assert_held_write(&cxl_dpa_rwsem); lockdep_assert_held_write(&cxl_rwsem.dpa); if (!len) { dev_warn(dev, "decoder%d.%d: empty reservation attempted\n", Loading Loading @@ -470,7 +473,7 @@ int cxl_dpa_setup(struct cxl_dev_state *cxlds, const struct cxl_dpa_info *info) { struct device *dev = cxlds->dev; guard(rwsem_write)(&cxl_dpa_rwsem); guard(rwsem_write)(&cxl_rwsem.dpa); if (cxlds->nr_partitions) return -EBUSY; Loading Loading @@ -516,9 +519,8 @@ int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled, struct cxl_port *port = cxled_to_port(cxled); int rc; down_write(&cxl_dpa_rwsem); scoped_guard(rwsem_write, &cxl_rwsem.dpa) rc = __cxl_dpa_reserve(cxled, base, len, skipped); up_write(&cxl_dpa_rwsem); if (rc) return rc; Loading @@ -529,7 +531,7 @@ EXPORT_SYMBOL_NS_GPL(devm_cxl_dpa_reserve, "CXL"); resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled) { guard(rwsem_read)(&cxl_dpa_rwsem); guard(rwsem_read)(&cxl_rwsem.dpa); if (cxled->dpa_res) return resource_size(cxled->dpa_res); Loading @@ -540,7 +542,7 @@ resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled) { resource_size_t base = -1; lockdep_assert_held(&cxl_dpa_rwsem); lockdep_assert_held(&cxl_rwsem.dpa); if (cxled->dpa_res) base = cxled->dpa_res->start; Loading @@ -559,7 +561,7 @@ int cxl_dpa_free(struct cxl_endpoint_decoder *cxled) struct cxl_port *port = cxled_to_port(cxled); struct device *dev = &cxled->cxld.dev; guard(rwsem_write)(&cxl_dpa_rwsem); guard(rwsem_write)(&cxl_rwsem.dpa); if (!cxled->dpa_res) return 0; if (cxled->cxld.region) { Loading Loading @@ -589,7 +591,7 @@ int cxl_dpa_set_part(struct cxl_endpoint_decoder *cxled, struct device *dev = &cxled->cxld.dev; int part; guard(rwsem_write)(&cxl_dpa_rwsem); guard(rwsem_write)(&cxl_rwsem.dpa); if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) return -EBUSY; Loading Loading @@ -621,7 +623,7 @@ static int __cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, u64 size) struct resource *p, *last; int part; guard(rwsem_write)(&cxl_dpa_rwsem); guard(rwsem_write)(&cxl_rwsem.dpa); if (cxled->cxld.region) { dev_dbg(dev, "decoder attached to %s\n", dev_name(&cxled->cxld.region->dev)); Loading Loading @@ -771,46 +773,12 @@ static int cxld_await_commit(void __iomem *hdm, int id) return -ETIMEDOUT; } static int cxl_decoder_commit(struct cxl_decoder *cxld) static void setup_hw_decoder(struct cxl_decoder *cxld, void __iomem *hdm) { struct cxl_port *port = to_cxl_port(cxld->dev.parent); struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev); void __iomem *hdm = cxlhdm->regs.hdm_decoder; int id = cxld->id, rc; int id = cxld->id; u64 base, size; u32 ctrl; if (cxld->flags & CXL_DECODER_F_ENABLE) return 0; if (cxl_num_decoders_committed(port) != id) { dev_dbg(&port->dev, "%s: out of order commit, expected decoder%d.%d\n", dev_name(&cxld->dev), port->id, cxl_num_decoders_committed(port)); return -EBUSY; } /* * For endpoint decoders hosted on CXL memory devices that * support the sanitize operation, make sure sanitize is not in-flight. */ if (is_endpoint_decoder(&cxld->dev)) { struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(&cxld->dev); struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); if (mds && mds->security.sanitize_active) { dev_dbg(&cxlmd->dev, "attempted to commit %s during sanitize\n", dev_name(&cxld->dev)); return -EBUSY; } } down_read(&cxl_dpa_rwsem); /* common decoder settings */ ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(cxld->id)); cxld_set_interleave(cxld, &ctrl); Loading Loading @@ -844,7 +812,47 @@ static int cxl_decoder_commit(struct cxl_decoder *cxld) } writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id)); up_read(&cxl_dpa_rwsem); } static int cxl_decoder_commit(struct cxl_decoder *cxld) { struct cxl_port *port = to_cxl_port(cxld->dev.parent); struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev); void __iomem *hdm = cxlhdm->regs.hdm_decoder; int id = cxld->id, rc; if (cxld->flags & CXL_DECODER_F_ENABLE) return 0; if (cxl_num_decoders_committed(port) != id) { dev_dbg(&port->dev, "%s: out of order commit, expected decoder%d.%d\n", dev_name(&cxld->dev), port->id, cxl_num_decoders_committed(port)); return -EBUSY; } /* * For endpoint decoders hosted on CXL memory devices that * support the sanitize operation, make sure sanitize is not in-flight. */ if (is_endpoint_decoder(&cxld->dev)) { struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(&cxld->dev); struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); if (mds && mds->security.sanitize_active) { dev_dbg(&cxlmd->dev, "attempted to commit %s during sanitize\n", dev_name(&cxld->dev)); return -EBUSY; } } scoped_guard(rwsem_read, &cxl_rwsem.dpa) setup_hw_decoder(cxld, hdm); port->commit_end++; rc = cxld_await_commit(hdm, cxld->id); Loading Loading @@ -882,7 +890,7 @@ void cxl_port_commit_reap(struct cxl_decoder *cxld) { struct cxl_port *port = to_cxl_port(cxld->dev.parent); lockdep_assert_held_write(&cxl_region_rwsem); lockdep_assert_held_write(&cxl_rwsem.region); /* * Once the highest committed decoder is disabled, free any other Loading Loading @@ -914,7 +922,6 @@ static void cxl_decoder_reset(struct cxl_decoder *cxld) "%s: out of order reset, expected decoder%d.%d\n", dev_name(&cxld->dev), port->id, port->commit_end); down_read(&cxl_dpa_rwsem); ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id)); ctrl &= ~CXL_HDM_DECODER0_CTRL_COMMIT; writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id)); Loading @@ -923,7 +930,6 @@ static void cxl_decoder_reset(struct cxl_decoder *cxld) writel(0, hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(id)); writel(0, hdm + CXL_HDM_DECODER0_BASE_HIGH_OFFSET(id)); writel(0, hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(id)); up_read(&cxl_dpa_rwsem); cxld->flags &= ~CXL_DECODER_F_ENABLE; Loading Loading @@ -1032,7 +1038,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, else cxld->target_type = CXL_DECODER_DEVMEM; guard(rwsem_write)(&cxl_region_rwsem); guard(rwsem_write)(&cxl_rwsem.region); if (cxld->id != cxl_num_decoders_committed(port)) { dev_warn(&port->dev, "decoder%d.%d: Committed out of order\n", Loading
drivers/cxl/core/mbox.c +6 −7 Original line number Diff line number Diff line Loading @@ -909,8 +909,8 @@ void cxl_event_trace_record(const struct cxl_memdev *cxlmd, * translations. Take topology mutation locks and lookup * { HPA, REGION } from { DPA, MEMDEV } in the event record. */ guard(rwsem_read)(&cxl_region_rwsem); guard(rwsem_read)(&cxl_dpa_rwsem); guard(rwsem_read)(&cxl_rwsem.region); guard(rwsem_read)(&cxl_rwsem.dpa); dpa = le64_to_cpu(evt->media_hdr.phys_addr) & CXL_DPA_MASK; cxlr = cxl_dpa_to_region(cxlmd, dpa); Loading Loading @@ -1265,7 +1265,7 @@ int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd) /* synchronize with cxl_mem_probe() and decoder write operations */ guard(device)(&cxlmd->dev); endpoint = cxlmd->endpoint; guard(rwsem_read)(&cxl_region_rwsem); guard(rwsem_read)(&cxl_rwsem.region); /* * Require an endpoint to be safe otherwise the driver can not * be sure that the device is unmapped. Loading Loading @@ -1401,8 +1401,8 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, int nr_records = 0; int rc; rc = mutex_lock_interruptible(&mds->poison.lock); if (rc) ACQUIRE(mutex_intr, lock)(&mds->poison.mutex); if ((rc = ACQUIRE_ERR(mutex_intr, &lock))) return rc; po = mds->poison.list_out; Loading Loading @@ -1437,7 +1437,6 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, } } while (po->flags & CXL_POISON_FLAG_MORE); mutex_unlock(&mds->poison.lock); return rc; } EXPORT_SYMBOL_NS_GPL(cxl_mem_get_poison, "CXL"); Loading Loading @@ -1473,7 +1472,7 @@ int cxl_poison_state_init(struct cxl_memdev_state *mds) return rc; } mutex_init(&mds->poison.lock); mutex_init(&mds->poison.mutex); return 0; } EXPORT_SYMBOL_NS_GPL(cxl_poison_state_init, "CXL"); Loading