Commit 7aacc625 authored by Dave Jiang's avatar Dave Jiang
Browse files

Merge branch 'for-7.1/cxl-type2-support' into cxl-for-next

Prep patches for CXL type2 accelerator basic support

cxl/region: Factor out interleave granularity setup
cxl/region: Factor out interleave ways setup
cxl: Make region type based on endpoint type
cxl/pci: Remove redundant cxl_pci_find_port() call
cxl: Move pci generic code from cxl_pci to core/cxl_pci
cxl: export internal structs for external Type2 drivers
cxl: support Type2 when initializing cxl_dev_state
parents 2fb3bdeb 64584273
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -224,4 +224,6 @@ int cxl_set_feature(struct cxl_mailbox *cxl_mbox, const uuid_t *feat_uuid,
		    u16 *return_code);
#endif

resource_size_t cxl_rcd_component_reg_phys(struct device *dev,
					   struct cxl_dport *dport);
#endif /* __CXL_CORE_H__ */
+5 −7
Original line number Diff line number Diff line
@@ -1522,23 +1522,21 @@ int cxl_mailbox_init(struct cxl_mailbox *cxl_mbox, struct device *host)
}
EXPORT_SYMBOL_NS_GPL(cxl_mailbox_init, "CXL");

struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev, u64 serial,
						 u16 dvsec)
{
	struct cxl_memdev_state *mds;
	int rc;

	mds = devm_kzalloc(dev, sizeof(*mds), GFP_KERNEL);
	mds = devm_cxl_dev_state_create(dev, CXL_DEVTYPE_CLASSMEM, serial,
					dvsec, struct cxl_memdev_state, cxlds,
					true);
	if (!mds) {
		dev_err(dev, "No memory available\n");
		return ERR_PTR(-ENOMEM);
	}

	mutex_init(&mds->event.log_lock);
	mds->cxlds.dev = dev;
	mds->cxlds.reg_map.host = dev;
	mds->cxlds.cxl_mbox.host = dev;
	mds->cxlds.reg_map.resource = CXL_RESOURCE_NONE;
	mds->cxlds.type = CXL_DEVTYPE_CLASSMEM;

	rc = devm_cxl_register_mce_notifier(dev, &mds->mce_notifier);
	if (rc == -EOPNOTSUPP)
+24 −0
Original line number Diff line number Diff line
@@ -659,6 +659,30 @@ static void detach_memdev(struct work_struct *work)

static struct lock_class_key cxl_memdev_key;

struct cxl_dev_state *_devm_cxl_dev_state_create(struct device *dev,
						 enum cxl_devtype type,
						 u64 serial, u16 dvsec,
						 size_t size, bool has_mbox)
{
	struct cxl_dev_state *cxlds = devm_kzalloc(dev, size, GFP_KERNEL);

	if (!cxlds)
		return NULL;

	cxlds->dev = dev;
	cxlds->type = type;
	cxlds->serial = serial;
	cxlds->cxl_dvsec = dvsec;
	cxlds->reg_map.host = dev;
	cxlds->reg_map.resource = CXL_RESOURCE_NONE;

	if (has_mbox)
		cxlds->cxl_mbox.host = dev;

	return cxlds;
}
EXPORT_SYMBOL_NS_GPL(_devm_cxl_dev_state_create, "CXL");

static struct cxl_memdev *cxl_memdev_alloc(struct cxl_dev_state *cxlds,
					   const struct file_operations *fops,
					   const struct cxl_memdev_attach *attach)
+57 −0
Original line number Diff line number Diff line
@@ -696,6 +696,63 @@ bool cxl_endpoint_decoder_reset_detected(struct cxl_port *port)
}
EXPORT_SYMBOL_NS_GPL(cxl_endpoint_decoder_reset_detected, "CXL");

static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
				  struct cxl_register_map *map,
				  struct cxl_dport *dport)
{
	resource_size_t component_reg_phys;

	*map = (struct cxl_register_map) {
		.host = &pdev->dev,
		.resource = CXL_RESOURCE_NONE,
	};

	component_reg_phys = cxl_rcd_component_reg_phys(&pdev->dev, dport);
	if (component_reg_phys == CXL_RESOURCE_NONE)
		return -ENXIO;

	map->resource = component_reg_phys;
	map->reg_type = CXL_REGLOC_RBI_COMPONENT;
	map->max_size = CXL_COMPONENT_REG_BLOCK_SIZE;

	return 0;
}

int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
		       struct cxl_register_map *map)
{
	int rc;

	rc = cxl_find_regblock(pdev, type, map);

	/*
	 * If the Register Locator DVSEC does not exist, check if it
	 * is an RCH and try to extract the Component Registers from
	 * an RCRB.
	 */
	if (rc && type == CXL_REGLOC_RBI_COMPONENT && is_cxl_restricted(pdev)) {
		struct cxl_dport *dport;
		struct cxl_port *port __free(put_cxl_port) =
			cxl_pci_find_port(pdev, &dport);
		if (!port)
			return -EPROBE_DEFER;

		rc = cxl_rcrb_get_comp_regs(pdev, map, dport);
		if (rc)
			return rc;

		rc = cxl_dport_map_rcd_linkcap(pdev, dport);
		if (rc)
			return rc;

	} else if (rc) {
		return rc;
	}

	return cxl_setup_regs(map);
}
EXPORT_SYMBOL_NS_GPL(cxl_pci_setup_regs, "CXL");

int cxl_pci_get_bandwidth(struct pci_dev *pdev, struct access_coordinate *c)
{
	int speed, bw;
+56 −31
Original line number Diff line number Diff line
@@ -485,22 +485,14 @@ static ssize_t interleave_ways_show(struct device *dev,

static const struct attribute_group *get_cxl_region_target_group(void);

static ssize_t interleave_ways_store(struct device *dev,
				     struct device_attribute *attr,
				     const char *buf, size_t len)
static int set_interleave_ways(struct cxl_region *cxlr, int val)
{
	struct cxl_region *cxlr = to_cxl_region(dev);
	struct cxl_root_decoder *cxlrd = cxlr->cxlrd;
	struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld;
	struct cxl_region_params *p = &cxlr->params;
	unsigned int val, save;
	int rc;
	int save, rc;
	u8 iw;

	rc = kstrtouint(buf, 0, &val);
	if (rc)
		return rc;

	rc = ways_to_eiw(val, &iw);
	if (rc)
		return rc;
@@ -515,9 +507,7 @@ static ssize_t interleave_ways_store(struct device *dev,
		return -EINVAL;
	}

	ACQUIRE(rwsem_write_kill, rwsem)(&cxl_rwsem.region);
	if ((rc = ACQUIRE_ERR(rwsem_write_kill, &rwsem)))
		return rc;
	lockdep_assert_held_write(&cxl_rwsem.region);

	if (p->state >= CXL_CONFIG_INTERLEAVE_ACTIVE)
		return -EBUSY;
@@ -525,11 +515,32 @@ static ssize_t interleave_ways_store(struct device *dev,
	save = p->interleave_ways;
	p->interleave_ways = val;
	rc = sysfs_update_group(&cxlr->dev.kobj, get_cxl_region_target_group());
	if (rc) {
	if (rc)
		p->interleave_ways = save;

	return rc;
}

static ssize_t interleave_ways_store(struct device *dev,
				     struct device_attribute *attr,
				     const char *buf, size_t len)
{
	struct cxl_region *cxlr = to_cxl_region(dev);
	int val;
	int rc;

	rc = kstrtoint(buf, 0, &val);
	if (rc)
		return rc;

	ACQUIRE(rwsem_write_kill, rwsem)(&cxl_rwsem.region);
	if ((rc = ACQUIRE_ERR(rwsem_write_kill, &rwsem)))
		return rc;

	rc = set_interleave_ways(cxlr, val);
	if (rc)
		return rc;

	return len;
}
static DEVICE_ATTR_RW(interleave_ways);
@@ -548,21 +559,14 @@ static ssize_t interleave_granularity_show(struct device *dev,
	return sysfs_emit(buf, "%d\n", p->interleave_granularity);
}

static ssize_t interleave_granularity_store(struct device *dev,
					    struct device_attribute *attr,
					    const char *buf, size_t len)
static int set_interleave_granularity(struct cxl_region *cxlr, int val)
{
	struct cxl_region *cxlr = to_cxl_region(dev);
	struct cxl_root_decoder *cxlrd = cxlr->cxlrd;
	struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld;
	struct cxl_region_params *p = &cxlr->params;
	int rc, val;
	int rc;
	u16 ig;

	rc = kstrtoint(buf, 0, &val);
	if (rc)
		return rc;

	rc = granularity_to_eig(val, &ig);
	if (rc)
		return rc;
@@ -578,14 +582,33 @@ static ssize_t interleave_granularity_store(struct device *dev,
	if (cxld->interleave_ways > 1 && val != cxld->interleave_granularity)
		return -EINVAL;

	ACQUIRE(rwsem_write_kill, rwsem)(&cxl_rwsem.region);
	if ((rc = ACQUIRE_ERR(rwsem_write_kill, &rwsem)))
		return rc;
	lockdep_assert_held_write(&cxl_rwsem.region);

	if (p->state >= CXL_CONFIG_INTERLEAVE_ACTIVE)
		return -EBUSY;

	p->interleave_granularity = val;
	return 0;
}

static ssize_t interleave_granularity_store(struct device *dev,
					    struct device_attribute *attr,
					    const char *buf, size_t len)
{
	struct cxl_region *cxlr = to_cxl_region(dev);
	int rc, val;

	rc = kstrtoint(buf, 0, &val);
	if (rc)
		return rc;

	ACQUIRE(rwsem_write_kill, rwsem)(&cxl_rwsem.region);
	if ((rc = ACQUIRE_ERR(rwsem_write_kill, &rwsem)))
		return rc;

	rc = set_interleave_granularity(cxlr, val);
	if (rc)
		return rc;

	return len;
}
@@ -2667,7 +2690,8 @@ static ssize_t create_ram_region_show(struct device *dev,
}

static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd,
					  enum cxl_partition_mode mode, int id)
					  enum cxl_partition_mode mode, int id,
					  enum cxl_decoder_type target_type)
{
	int rc;

@@ -2689,7 +2713,7 @@ static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd,
		return ERR_PTR(-EBUSY);
	}

	return devm_cxl_add_region(cxlrd, id, mode, CXL_DECODER_HOSTONLYMEM);
	return devm_cxl_add_region(cxlrd, id, mode, target_type);
}

static ssize_t create_region_store(struct device *dev, const char *buf,
@@ -2703,7 +2727,7 @@ static ssize_t create_region_store(struct device *dev, const char *buf,
	if (rc != 1)
		return -EINVAL;

	cxlr = __create_region(cxlrd, mode, id);
	cxlr = __create_region(cxlrd, mode, id, CXL_DECODER_HOSTONLYMEM);
	if (IS_ERR(cxlr))
		return PTR_ERR(cxlr);

@@ -3921,7 +3945,8 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,

	do {
		cxlr = __create_region(cxlrd, cxlds->part[part].mode,
				       atomic_read(&cxlrd->region_id));
				       atomic_read(&cxlrd->region_id),
				       cxled->cxld.target_type);
	} while (IS_ERR(cxlr) && PTR_ERR(cxlr) == -EBUSY);

	if (IS_ERR(cxlr)) {
Loading