new file mode 100644
@@ -0,0 +1,54 @@
+What: /sys/bus/cdx/rescan
+Date: August 2022
+Contact: puneet.gupta@amd.com
+Description:
+ Writing 1 to this would cause rescan of the bus
+ and devices on the CDX bus. Any new devices would
+ be scanned and added to the list of linux devices
+ and any devices removed are also deleted from linux.
+
+ For example::
+
+ # echo 1 > /sys/bus/cdx/rescan
+
+What: /sys/bus/cdx/reset_all
+Date: August 2022
+Contact: puneet.gupta@amd.com
+Description:
+ Writing 1 to this would reset all the devices present
+ on the CDX bus
+
+ For example::
+
+ # echo 1 > /sys/bus/cdx/reset_all
+
+What: /sys/bus/cdx/devices/.../vendor
+Date: August 2022
+Contact: nipun.gupta@amd.com
+Description:
+ Vendor ID for this CDX device
+
+What: /sys/bus/cdx/devices/.../device
+Date: August 2022
+Contact: nipun.gupta@amd.com
+Description:
+ Device ID for this CDX device
+
+What: /sys/bus/cdx/devices/.../reset
+What: /sys/bus/cdx/devices/.../reset
+Date: August 2022
+Contact: nipun.gupta@amd.com
+Description:
+ Writing 1 to this would reset the CDX device
+
+ For example::
+
+ # echo 1 > /sys/bus/cdx/.../reset
+
+What: /sys/bus/cdx/devices/.../modalias
+Date: August 2022
+Contact: nipun.gupta@amd.com
+Description:
+ A CDX device has modalias:
+
+ - v`vendor`d`device`
@@ -32,6 +32,23 @@ struct platform_device *cdx_controller_pdev;
static int cdx_bus_device_discovery(struct platform_device *pdev);
+static int reset_cdx_device(struct device *dev, void * __always_unused data)
+{
+ struct platform_device *cdx_bus_pdev = to_platform_device(dev->parent);
+ struct cdx_device *cdx_dev = to_cdx_device(dev);
+ struct cdx_mcdi_t *cdx_mcdi = platform_get_drvdata(cdx_bus_pdev);
+
+ /* MCDI FW: reset particular device represented by bus:func */
+ cdx_mcdi_func_reset(cdx_mcdi, cdx_dev->bus_id, cdx_dev->func_id);
+
+ return 0;
+}
+
+int cdx_dev_reset(struct device *dev)
+{
+ return reset_cdx_device(dev, NULL);
+}
+
static int cdx_unregister_device(struct device *dev,
void * __always_unused data)
{
@@ -139,10 +156,141 @@ static int cdx_dma_configure(struct device *dev)
return 0;
}
+static ssize_t vendor_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct cdx_device *cdx_dev = to_cdx_device(dev);
+
+ return sprintf(buf, "0x%x\n", cdx_dev->vendor);
+}
+static DEVICE_ATTR_RO(vendor);
+
+static ssize_t device_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct cdx_device *cdx_dev = to_cdx_device(dev);
+
+ return sprintf(buf, "0x%x\n", cdx_dev->device);
+}
+static DEVICE_ATTR_RO(device);
+
+static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret = 0;
+ bool reset = count > 0 && *buf != '0';
+
+ if (!reset)
+ return count;
+
+ ret = reset_cdx_device(dev, NULL);
+ if (ret)
+ return ret;
+
+ return count;
+}
+static DEVICE_ATTR_WO(reset);
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct cdx_device *cdx_dev = to_cdx_device(dev);
+
+ return sprintf(buf, "cdx:v%08Xd%d\n", cdx_dev->vendor,
+ cdx_dev->device);
+}
+static DEVICE_ATTR_RO(modalias);
+
+static ssize_t driver_override_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cdx_device *cdx_dev = to_cdx_device(dev);
+ int ret;
+
+ if (WARN_ON(dev->bus != &cdx_bus_type))
+ return -EINVAL;
+
+ ret = driver_set_override(dev, &cdx_dev->driver_override, buf, count);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static ssize_t driver_override_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cdx_device *cdx_dev = to_cdx_device(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", cdx_dev->driver_override);
+}
+static DEVICE_ATTR_RW(driver_override);
+
+static struct attribute *cdx_dev_attrs[] = {
+ &dev_attr_reset.attr,
+ &dev_attr_vendor.attr,
+ &dev_attr_device.attr,
+ &dev_attr_modalias.attr,
+ &dev_attr_driver_override.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(cdx_dev);
+
+static ssize_t rescan_store(struct bus_type *bus,
+ const char *buf, size_t count)
+{
+ bool rescan = count > 0 && *buf != '0';
+ int ret = 0;
+
+ if (!rescan)
+ return count;
+
+ /* Unregister all the devices on the bus */
+ cdx_unregister_devices(&cdx_bus_type);
+
+ /* Rescan all the devices */
+ ret = cdx_bus_device_discovery(cdx_controller_pdev);
+ if (ret)
+ return ret;
+
+ return count;
+}
+static BUS_ATTR_WO(rescan);
+
+static ssize_t reset_all_store(struct bus_type *bus,
+ const char *buf, size_t count)
+{
+ bool reset = count > 0 && *buf != '0';
+ int ret = 0;
+
+ if (!reset)
+ return count;
+
+ /* Reset all the devices attached to cdx bus */
+ ret = bus_for_each_dev(bus, NULL, NULL, reset_cdx_device);
+ if (ret) {
+ pr_err("error in CDX bus reset\n");
+ return 0;
+ }
+
+ return count;
+}
+static BUS_ATTR_WO(reset_all);
+
+static struct attribute *cdx_bus_attrs[] = {
+ &bus_attr_rescan.attr,
+ &bus_attr_reset_all.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(cdx_bus);
+
struct bus_type cdx_bus_type = {
.name = "cdx",
.match = cdx_bus_match,
.dma_configure = cdx_dma_configure,
+ .dev_groups = cdx_dev_groups,
+ .bus_groups = cdx_bus_groups,
};
EXPORT_SYMBOL_GPL(cdx_bus_type);
@@ -53,3 +53,9 @@ int cdx_mcdi_get_func_config(struct cdx_mcdi_t *cdx_mcdi,
return 0;
}
+
+int cdx_mcdi_func_reset(struct cdx_mcdi_t *cdx_mcdi,
+ uint8_t bus_id, uint8_t func_id)
+{
+ return 0;
+}
@@ -73,4 +73,15 @@ int cdx_mcdi_get_func_config(struct cdx_mcdi_t *cdx_mcdi,
uint8_t bus_id, uint8_t func_id,
struct cdx_dev_params_t *dev_params);
+/**
+ * cdx_mcdi_func_reset - Reset cdx device represented by bus_id:func_id
+ * @cdx_mcdi: pointer to MCDI interface.
+ * @bus_num: Bus number.
+ * @func_id: Function number.
+ *
+ * Return 0 on success, <0 on failure
+ */
+int cdx_mcdi_func_reset(struct cdx_mcdi_t *cdx_mcdi,
+ uint8_t bus_id, uint8_t func_id);
+
#endif /* _MCDI_STUBS_H_ */
@@ -109,4 +109,12 @@ int cdx_msi_domain_alloc_irqs(struct device *dev, unsigned int irq_count);
*/
void cdx_msi_domain_free_irqs(struct device *dev);
+/**
+ * cdx_dev_reset - Reset CDX device
+ * @dev: device pointer
+ *
+ * Return 0 for success, -errno on failure
+ */
+int cdx_dev_reset(struct device *dev);
+
#endif /* _CDX_BUS_H_ */