diff options
Diffstat (limited to 'drivers/misc/cxl/sysfs.c')
| -rw-r--r-- | drivers/misc/cxl/sysfs.c | 123 | 
1 files changed, 91 insertions, 32 deletions
| diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c index 038af5d45145..25913c08794c 100644 --- a/drivers/misc/cxl/sysfs.c +++ b/drivers/misc/cxl/sysfs.c @@ -69,7 +69,7 @@ static ssize_t reset_adapter_store(struct device *device,  	if ((rc != 1) || (val != 1))  		return -EINVAL; -	if ((rc = cxl_reset(adapter))) +	if ((rc = cxl_ops->adapter_reset(adapter)))  		return rc;  	return count;  } @@ -165,7 +165,7 @@ static ssize_t pp_mmio_off_show(struct device *device,  {  	struct cxl_afu *afu = to_afu_chardev_m(device); -	return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->pp_offset); +	return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->native->pp_offset);  }  static ssize_t pp_mmio_len_show(struct device *device, @@ -211,7 +211,7 @@ static ssize_t reset_store_afu(struct device *device,  		goto err;  	} -	if ((rc = __cxl_afu_reset(afu))) +	if ((rc = cxl_ops->afu_reset(afu)))  		goto err;  	rc = count; @@ -253,8 +253,14 @@ static ssize_t irqs_max_store(struct device *device,  	if (irqs_max < afu->pp_irqs)  		return -EINVAL; -	if (irqs_max > afu->adapter->user_irqs) -		return -EINVAL; +	if (cpu_has_feature(CPU_FTR_HVMODE)) { +		if (irqs_max > afu->adapter->user_irqs) +			return -EINVAL; +	} else { +		/* pHyp sets a per-AFU limit */ +		if (irqs_max > afu->guest->max_ints) +			return -EINVAL; +	}  	afu->irqs_max = irqs_max;  	return count; @@ -348,7 +354,7 @@ static ssize_t mode_store(struct device *device, struct device_attribute *attr,  	}  	/* -	 * cxl_afu_deactivate_mode needs to be done outside the lock, prevent +	 * afu_deactivate_mode needs to be done outside the lock, prevent  	 * other contexts coming in before we are ready:  	 */  	old_mode = afu->current_mode; @@ -357,9 +363,9 @@ static ssize_t mode_store(struct device *device, struct device_attribute *attr,  	mutex_unlock(&afu->contexts_lock); -	if ((rc = _cxl_afu_deactivate_mode(afu, old_mode))) +	if ((rc = cxl_ops->afu_deactivate_mode(afu, old_mode)))  		return rc; -	if ((rc = cxl_afu_activate_mode(afu, mode))) +	if ((rc = cxl_ops->afu_activate_mode(afu, mode)))  		return rc;  	return count; @@ -388,7 +394,7 @@ static ssize_t afu_eb_read(struct file *filp, struct kobject *kobj,  {  	struct cxl_afu *afu = to_cxl_afu(kobj_to_dev(kobj)); -	return cxl_afu_read_err_buffer(afu, buf, off, count); +	return cxl_ops->afu_read_err_buffer(afu, buf, off, count);  }  static struct device_attribute afu_attrs[] = { @@ -405,24 +411,39 @@ static struct device_attribute afu_attrs[] = {  int cxl_sysfs_adapter_add(struct cxl *adapter)  { +	struct device_attribute *dev_attr;  	int i, rc;  	for (i = 0; i < ARRAY_SIZE(adapter_attrs); i++) { -		if ((rc = device_create_file(&adapter->dev, &adapter_attrs[i]))) -			goto err; +		dev_attr = &adapter_attrs[i]; +		if (cxl_ops->support_attributes(dev_attr->attr.name, +						CXL_ADAPTER_ATTRS)) { +			if ((rc = device_create_file(&adapter->dev, dev_attr))) +				goto err; +		}  	}  	return 0;  err: -	for (i--; i >= 0; i--) -		device_remove_file(&adapter->dev, &adapter_attrs[i]); +	for (i--; i >= 0; i--) { +		dev_attr = &adapter_attrs[i]; +		if (cxl_ops->support_attributes(dev_attr->attr.name, +						CXL_ADAPTER_ATTRS)) +			device_remove_file(&adapter->dev, dev_attr); +	}  	return rc;  } +  void cxl_sysfs_adapter_remove(struct cxl *adapter)  { +	struct device_attribute *dev_attr;  	int i; -	for (i = 0; i < ARRAY_SIZE(adapter_attrs); i++) -		device_remove_file(&adapter->dev, &adapter_attrs[i]); +	for (i = 0; i < ARRAY_SIZE(adapter_attrs); i++) { +		dev_attr = &adapter_attrs[i]; +		if (cxl_ops->support_attributes(dev_attr->attr.name, +						CXL_ADAPTER_ATTRS)) +			device_remove_file(&adapter->dev, dev_attr); +	}  }  struct afu_config_record { @@ -468,10 +489,12 @@ static ssize_t afu_read_config(struct file *filp, struct kobject *kobj,  	struct afu_config_record *cr = to_cr(kobj);  	struct cxl_afu *afu = to_cxl_afu(kobj_to_dev(kobj->parent)); -	u64 i, j, val; +	u64 i, j, val, rc;  	for (i = 0; i < count;) { -		val = cxl_afu_cr_read64(afu, cr->cr, off & ~0x7); +		rc = cxl_ops->afu_cr_read64(afu, cr->cr, off & ~0x7, &val); +		if (rc) +			val = ~0ULL;  		for (j = off & 0x7; j < 8 && i < count; i++, j++, off++)  			buf[i] = (val >> (j * 8)) & 0xff;  	} @@ -516,14 +539,22 @@ static struct afu_config_record *cxl_sysfs_afu_new_cr(struct cxl_afu *afu, int c  		return ERR_PTR(-ENOMEM);  	cr->cr = cr_idx; -	cr->device = cxl_afu_cr_read16(afu, cr_idx, PCI_DEVICE_ID); -	cr->vendor = cxl_afu_cr_read16(afu, cr_idx, PCI_VENDOR_ID); -	cr->class = cxl_afu_cr_read32(afu, cr_idx, PCI_CLASS_REVISION) >> 8; + +	rc = cxl_ops->afu_cr_read16(afu, cr_idx, PCI_DEVICE_ID, &cr->device); +	if (rc) +		goto err; +	rc = cxl_ops->afu_cr_read16(afu, cr_idx, PCI_VENDOR_ID, &cr->vendor); +	if (rc) +		goto err; +	rc = cxl_ops->afu_cr_read32(afu, cr_idx, PCI_CLASS_REVISION, &cr->class); +	if (rc) +		goto err; +	cr->class >>= 8;  	/*  	 * Export raw AFU PCIe like config record. For now this is read only by  	 * root - we can expand that later to be readable by non-root and maybe -	 * even writable provided we have a good use-case. Once we suport +	 * even writable provided we have a good use-case. Once we support  	 * exposing AFUs through a virtual PHB they will get that for free from  	 * Linux' PCI infrastructure, but until then it's not clear that we  	 * need it for anything since the main use case is just identifying @@ -561,6 +592,7 @@ err:  void cxl_sysfs_afu_remove(struct cxl_afu *afu)  { +	struct device_attribute *dev_attr;  	struct afu_config_record *cr, *tmp;  	int i; @@ -568,8 +600,12 @@ void cxl_sysfs_afu_remove(struct cxl_afu *afu)  	if (afu->eb_len)  		device_remove_bin_file(&afu->dev, &afu->attr_eb); -	for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) -		device_remove_file(&afu->dev, &afu_attrs[i]); +	for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) { +		dev_attr = &afu_attrs[i]; +		if (cxl_ops->support_attributes(dev_attr->attr.name, +						CXL_AFU_ATTRS)) +			device_remove_file(&afu->dev, &afu_attrs[i]); +	}  	list_for_each_entry_safe(cr, tmp, &afu->crs, list) {  		sysfs_remove_bin_file(&cr->kobj, &cr->config_attr); @@ -579,14 +615,19 @@ void cxl_sysfs_afu_remove(struct cxl_afu *afu)  int cxl_sysfs_afu_add(struct cxl_afu *afu)  { +	struct device_attribute *dev_attr;  	struct afu_config_record *cr;  	int i, rc;  	INIT_LIST_HEAD(&afu->crs);  	for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) { -		if ((rc = device_create_file(&afu->dev, &afu_attrs[i]))) -			goto err; +		dev_attr = &afu_attrs[i]; +		if (cxl_ops->support_attributes(dev_attr->attr.name, +						CXL_AFU_ATTRS)) { +			if ((rc = device_create_file(&afu->dev, &afu_attrs[i]))) +				goto err; +		}  	}  	/* conditionally create the add the binary file for error info buffer */ @@ -625,32 +666,50 @@ err:  	/* reset the eb_len as we havent created the bin attr */  	afu->eb_len = 0; -	for (i--; i >= 0; i--) +	for (i--; i >= 0; i--) { +		dev_attr = &afu_attrs[i]; +		if (cxl_ops->support_attributes(dev_attr->attr.name, +						CXL_AFU_ATTRS))  		device_remove_file(&afu->dev, &afu_attrs[i]); +	}  	return rc;  }  int cxl_sysfs_afu_m_add(struct cxl_afu *afu)  { +	struct device_attribute *dev_attr;  	int i, rc;  	for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++) { -		if ((rc = device_create_file(afu->chardev_m, &afu_master_attrs[i]))) -			goto err; +		dev_attr = &afu_master_attrs[i]; +		if (cxl_ops->support_attributes(dev_attr->attr.name, +						CXL_AFU_MASTER_ATTRS)) { +			if ((rc = device_create_file(afu->chardev_m, &afu_master_attrs[i]))) +				goto err; +		}  	}  	return 0;  err: -	for (i--; i >= 0; i--) -		device_remove_file(afu->chardev_m, &afu_master_attrs[i]); +	for (i--; i >= 0; i--) { +		dev_attr = &afu_master_attrs[i]; +		if (cxl_ops->support_attributes(dev_attr->attr.name, +						CXL_AFU_MASTER_ATTRS)) +			device_remove_file(afu->chardev_m, &afu_master_attrs[i]); +	}  	return rc;  }  void cxl_sysfs_afu_m_remove(struct cxl_afu *afu)  { +	struct device_attribute *dev_attr;  	int i; -	for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++) -		device_remove_file(afu->chardev_m, &afu_master_attrs[i]); +	for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++) { +		dev_attr = &afu_master_attrs[i]; +		if (cxl_ops->support_attributes(dev_attr->attr.name, +						CXL_AFU_MASTER_ATTRS)) +			device_remove_file(afu->chardev_m, &afu_master_attrs[i]); +	}  } | 
