|
@@ -20,7 +20,9 @@
|
|
|
|
|
|
#include <linux/acpi_iort.h>
|
|
|
#include <linux/kernel.h>
|
|
|
+#include <linux/list.h>
|
|
|
#include <linux/pci.h>
|
|
|
+#include <linux/slab.h>
|
|
|
|
|
|
struct iort_its_msi_chip {
|
|
|
struct list_head list;
|
|
@@ -28,6 +30,90 @@ struct iort_its_msi_chip {
|
|
|
u32 translation_id;
|
|
|
};
|
|
|
|
|
|
+struct iort_fwnode {
|
|
|
+ struct list_head list;
|
|
|
+ struct acpi_iort_node *iort_node;
|
|
|
+ struct fwnode_handle *fwnode;
|
|
|
+};
|
|
|
+static LIST_HEAD(iort_fwnode_list);
|
|
|
+static DEFINE_SPINLOCK(iort_fwnode_lock);
|
|
|
+
|
|
|
+/**
|
|
|
+ * iort_set_fwnode() - Create iort_fwnode and use it to register
|
|
|
+ * iommu data in the iort_fwnode_list
|
|
|
+ *
|
|
|
+ * @node: IORT table node associated with the IOMMU
|
|
|
+ * @fwnode: fwnode associated with the IORT node
|
|
|
+ *
|
|
|
+ * Returns: 0 on success
|
|
|
+ * <0 on failure
|
|
|
+ */
|
|
|
+static inline int iort_set_fwnode(struct acpi_iort_node *iort_node,
|
|
|
+ struct fwnode_handle *fwnode)
|
|
|
+{
|
|
|
+ struct iort_fwnode *np;
|
|
|
+
|
|
|
+ np = kzalloc(sizeof(struct iort_fwnode), GFP_ATOMIC);
|
|
|
+
|
|
|
+ if (WARN_ON(!np))
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ INIT_LIST_HEAD(&np->list);
|
|
|
+ np->iort_node = iort_node;
|
|
|
+ np->fwnode = fwnode;
|
|
|
+
|
|
|
+ spin_lock(&iort_fwnode_lock);
|
|
|
+ list_add_tail(&np->list, &iort_fwnode_list);
|
|
|
+ spin_unlock(&iort_fwnode_lock);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * iort_get_fwnode() - Retrieve fwnode associated with an IORT node
|
|
|
+ *
|
|
|
+ * @node: IORT table node to be looked-up
|
|
|
+ *
|
|
|
+ * Returns: fwnode_handle pointer on success, NULL on failure
|
|
|
+ */
|
|
|
+static inline
|
|
|
+struct fwnode_handle *iort_get_fwnode(struct acpi_iort_node *node)
|
|
|
+{
|
|
|
+ struct iort_fwnode *curr;
|
|
|
+ struct fwnode_handle *fwnode = NULL;
|
|
|
+
|
|
|
+ spin_lock(&iort_fwnode_lock);
|
|
|
+ list_for_each_entry(curr, &iort_fwnode_list, list) {
|
|
|
+ if (curr->iort_node == node) {
|
|
|
+ fwnode = curr->fwnode;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ spin_unlock(&iort_fwnode_lock);
|
|
|
+
|
|
|
+ return fwnode;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * iort_delete_fwnode() - Delete fwnode associated with an IORT node
|
|
|
+ *
|
|
|
+ * @node: IORT table node associated with fwnode to delete
|
|
|
+ */
|
|
|
+static inline void iort_delete_fwnode(struct acpi_iort_node *node)
|
|
|
+{
|
|
|
+ struct iort_fwnode *curr, *tmp;
|
|
|
+
|
|
|
+ spin_lock(&iort_fwnode_lock);
|
|
|
+ list_for_each_entry_safe(curr, tmp, &iort_fwnode_list, list) {
|
|
|
+ if (curr->iort_node == node) {
|
|
|
+ list_del(&curr->list);
|
|
|
+ kfree(curr);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ spin_unlock(&iort_fwnode_lock);
|
|
|
+}
|
|
|
+
|
|
|
typedef acpi_status (*iort_find_node_callback)
|
|
|
(struct acpi_iort_node *node, void *context);
|
|
|
|