@@ -112,7 +112,7 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
}
/**
- * acpi_dma_parse_csrt - parse CSRT to exctract additional DMA resources
+ * acpi_dma_parse_csrt_shared_info - parse CSRT shared info to extract additional DMA resources
* @adev: ACPI device to match with
* @adma: struct acpi_dma of the given DMA controller
*
@@ -124,7 +124,7 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
* We are using this table to get the request line range of the specific DMA
* controller to be used later.
*/
-static void acpi_dma_parse_csrt(struct acpi_device *adev, struct acpi_dma *adma)
+static void acpi_dma_parse_csrt_shared_info(struct acpi_device *adev, struct acpi_dma *adma)
{
struct acpi_csrt_group *grp, *end;
struct acpi_table_csrt *csrt;
@@ -157,12 +157,64 @@ static void acpi_dma_parse_csrt(struct acpi_device *adev, struct acpi_dma *adma)
}
/**
- * acpi_dma_controller_register - Register a DMA controller to ACPI DMA helpers
- * @dev: struct device of DMA controller
- * @acpi_dma_xlate: translation function which converts a dma specifier
- * into a dma_chan structure
- * @data: pointer to controller specific data to be used by
- * translation function
+ * acpi_dma_get_csrt_dma_descriptors_by_uid - Get DMA descriptor from CSRT table for given id
+ * @adev: ACPI device node
+ * @uid: Unique ID for look up
+ *
+ * Parse CSRT table and look for DMA descriptors matching the given ID
+ *
+ * Return:
+ * Pointer to DMA descriptor on success or NULL on error/no match.
+ */
+struct acpi_csrt_descriptor *
+acpi_dma_get_csrt_dma_descriptors_by_uid(struct acpi_device *adev, uint32_t uid)
+{
+ struct acpi_csrt_descriptor *desc, *desc_end, *desc_found = NULL;
+ struct acpi_csrt_group *grp, *grp_end;
+ struct acpi_table_csrt *csrt;
+ acpi_status status;
+
+ status = acpi_get_table(ACPI_SIG_CSRT, 0,
+ (struct acpi_table_header **)&csrt);
+ if (ACPI_FAILURE(status)) {
+ if (status != AE_NOT_FOUND)
+ dev_warn(&adev->dev, "failed to get the CSRT table\n");
+ return NULL;
+ }
+
+ grp = (struct acpi_csrt_group *)(csrt + 1);
+ grp_end =
+ (struct acpi_csrt_group *)((void *)csrt + csrt->header.length);
+
+ while (grp < grp_end) {
+ desc = (struct acpi_csrt_descriptor *)((void *)(grp + 1) +
+ grp->shared_info_length);
+ desc_end = (struct acpi_csrt_descriptor *)((void *)grp +
+ grp->length);
+ while (desc < desc_end) {
+ if (desc->uid == uid) {
+ desc_found = desc;
+ goto found;
+ }
+ desc = (struct acpi_csrt_descriptor *)(((void *)desc) +
+ desc->length);
+ }
+ grp = (struct acpi_csrt_group *)((void *)grp + grp->length);
+ }
+
+found:
+ acpi_put_table((struct acpi_table_header *)csrt);
+
+ return desc_found;
+}
+
+/**
+ * acpi_dma_controller_register_with_csrt_shared_desc - Register a DMA controller to ACPI DMA helpers
+ * @dev: struct device of DMA controller
+ * @acpi_dma_xlate: translation function which converts a dma specifier
+ * into a dma_chan structure
+ * @data: pointer to controller specific data to be used by
+ * translation function
*
* Allocated memory should be freed with appropriate acpi_dma_controller_free()
* call.
@@ -170,16 +222,14 @@ static void acpi_dma_parse_csrt(struct acpi_device *adev, struct acpi_dma *adma)
* Return:
* 0 on success or appropriate errno value on error.
*/
-int acpi_dma_controller_register(struct device *dev,
- struct dma_chan *(*acpi_dma_xlate)
- (struct acpi_dma_spec *, struct acpi_dma *),
- void *data)
+int acpi_dma_controller_register_with_csrt_shared_desc(
+ struct device *dev,
+ struct dma_chan *(*acpi_dma_xlate)(struct acpi_dma_spec *,
+ struct acpi_dma *),
+ void *data)
{
struct acpi_device *adev;
- struct acpi_dma *adma;
-
- if (!dev || !acpi_dma_xlate)
- return -EINVAL;
+ struct acpi_dma *adma;
/* Check if the device was enumerated by ACPI */
adev = ACPI_COMPANION(dev);
@@ -194,7 +244,34 @@ int acpi_dma_controller_register(struct device *dev,
adma->acpi_dma_xlate = acpi_dma_xlate;
adma->data = data;
- acpi_dma_parse_csrt(adev, adma);
+ acpi_dma_parse_csrt_shared_info(adev, adma);
+
+ return acpi_dma_controller_register(dev, adma);
+}
+EXPORT_SYMBOL_GPL(acpi_dma_controller_register_with_csrt_shared_desc);
+
+/**
+ * acpi_dma_controller_register - Register a DMA controller to ACPI DMA helpers
+ * @dev: struct device of DMA controller
+ * @adma: ACPI DMA descriptor
+ *
+ * Allocated memory should be freed with appropriate acpi_dma_controller_free()
+ * call.
+ *
+ * Return:
+ * 0 on success or appropriate errno value on error.
+ */
+int acpi_dma_controller_register(struct device *dev, struct acpi_dma *adma)
+{
+ struct acpi_device *adev;
+
+ if (!dev || !adma || !adma->acpi_dma_xlate)
+ return -EINVAL;
+
+ /* Check if the device was enumerated by ACPI */
+ adev = ACPI_COMPANION(dev);
+ if (!adev)
+ return -EINVAL;
/* Now queue acpi_dma controller structure in list */
mutex_lock(&acpi_dma_lock);
@@ -244,8 +321,7 @@ static void devm_acpi_dma_release(struct device *dev, void *res)
/**
* devm_acpi_dma_controller_register - resource managed acpi_dma_controller_register()
* @dev: device that is registering this DMA controller
- * @acpi_dma_xlate: translation function
- * @data: pointer to controller specific data
+ * @adma: ACPI specific DMA descriptor
*
* Managed acpi_dma_controller_register(). DMA controller registered by this
* function are automatically freed on driver detach. See
@@ -254,10 +330,7 @@ static void devm_acpi_dma_release(struct device *dev, void *res)
* Return:
* 0 on success or appropriate errno value on error.
*/
-int devm_acpi_dma_controller_register(struct device *dev,
- struct dma_chan *(*acpi_dma_xlate)
- (struct acpi_dma_spec *, struct acpi_dma *),
- void *data)
+int devm_acpi_dma_controller_register(struct device *dev, struct acpi_dma *adma)
{
void *res;
int ret;
@@ -266,7 +339,7 @@ int devm_acpi_dma_controller_register(struct device *dev,
if (!res)
return -ENOMEM;
- ret = acpi_dma_controller_register(dev, acpi_dma_xlate, data);
+ ret = acpi_dma_controller_register(dev, adma);
if (ret) {
devres_free(res);
return ret;
@@ -37,7 +37,8 @@ void dw_dma_acpi_controller_register(struct dw_dma *dw)
dma_cap_set(DMA_SLAVE, info->dma_cap);
info->filter_fn = dw_dma_acpi_filter;
- ret = acpi_dma_controller_register(dev, acpi_dma_simple_xlate, info);
+ ret = acpi_dma_controller_register_with_csrt_shared_desc(
+ dev, acpi_dma_simple_xlate, info);
if (ret)
dev_err(dev, "could not register acpi_dma_controller\n");
}
@@ -56,15 +56,10 @@ struct acpi_dma_filter_info {
#ifdef CONFIG_DMA_ACPI
-int acpi_dma_controller_register(struct device *dev,
- struct dma_chan *(*acpi_dma_xlate)
- (struct acpi_dma_spec *, struct acpi_dma *),
- void *data);
+int acpi_dma_controller_register(struct device *dev, struct acpi_dma *adma);
int acpi_dma_controller_free(struct device *dev);
int devm_acpi_dma_controller_register(struct device *dev,
- struct dma_chan *(*acpi_dma_xlate)
- (struct acpi_dma_spec *, struct acpi_dma *),
- void *data);
+ struct acpi_dma *adma);
void devm_acpi_dma_controller_free(struct device *dev);
struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev,
@@ -74,23 +69,36 @@ struct dma_chan *acpi_dma_request_slave_chan_by_name(struct device *dev,
struct dma_chan *acpi_dma_simple_xlate(struct acpi_dma_spec *dma_spec,
struct acpi_dma *adma);
+struct acpi_csrt_descriptor *
+acpi_dma_get_csrt_dma_descriptors_by_uid(struct acpi_device *adev,
+ uint32_t uid);
+int acpi_dma_controller_register_with_csrt_shared_desc(
+ struct device *dev,
+ struct dma_chan *(*acpi_dma_xlate)(struct acpi_dma_spec *,
+ struct acpi_dma *),
+ void *data);
#else
-static inline int acpi_dma_controller_register(struct device *dev,
- struct dma_chan *(*acpi_dma_xlate)
- (struct acpi_dma_spec *, struct acpi_dma *),
- void *data)
+static inline int acpi_dma_controller_register(struct device *dev, struct acpi_dma *adma)
{
return -ENODEV;
}
+
+static inline int acpi_dma_controller_register_with_csrt_shared_desc(
+ struct device *dev,
+ struct dma_chan *(*acpi_dma_xlate)(struct acpi_dma_spec *,
+ struct acpi_dma *),
+ void *data)
+{
+ return -ENODEV;
+}
+
static inline int acpi_dma_controller_free(struct device *dev)
{
return -ENODEV;
}
static inline int devm_acpi_dma_controller_register(struct device *dev,
- struct dma_chan *(*acpi_dma_xlate)
- (struct acpi_dma_spec *, struct acpi_dma *),
- void *data)
+ struct acpi_dma *adma)
{
return -ENODEV;
}
@@ -109,7 +117,13 @@ static inline struct dma_chan *acpi_dma_request_slave_chan_by_name(
return ERR_PTR(-ENODEV);
}
-#define acpi_dma_simple_xlate NULL
+static inline struct acpi_csrt_descriptor *
+acpi_dma_get_csrt_dma_descriptors_by_uid(struct acpi_device *adev, uint32_t uid)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+#define acpi_dma_simple_xlate NULL
#endif