From 7f847dd31736f1284538e54f46cf10e63929eb7f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 20 Oct 2016 22:07:53 +0200 Subject: debugfs: improve DEFINE_DEBUGFS_ATTRIBUTE for !CONFIG_DEBUG_FS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The slp_s0_residency_usec debugfs file currently uses DEFINE_DEBUGFS_ATTRIBUTE(), but that macro cannot really be used to define files outside of the debugfs code, as it has no reference to the get/set functions if CONFIG_DEBUG_FS is not defined: drivers/platform/x86/intel_pmc_core.c:80:12: error: ‘pmc_core_dev_state_get’ defined but not used [-Werror=unused-function] This fixes the macro to always contain the reference, and instead rely on the stubbed-out debugfs_create_file to not actually refer to its arguments so the compiler can still drop the reference. This works because the attribute definition is always 'static', and the dead-code removal silently drops all static symbols that are not used. Fixes: c64688081490 ("debugfs: add support for self-protecting attribute file fops") Fixes: df2294fb6428 ("intel_pmc_core: Convert to DEFINE_DEBUGFS_ATTRIBUTE") Signed-off-by: Arnd Bergmann [nicstange@gmail.com: Add dummy implementations of debugfs_attr_read() and debugfs_attr_write() in order to protect against possibly broken dead code elimination and to improve readability. Correct CONFIG_DEBUGFS_FS -> CONFIG_DEBUG_FS typo in changelog.] Signed-off-by: Nicolai Stange Reviewed-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- include/linux/debugfs.h | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 4d3f0d1aec73..1b413a9aab81 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -62,6 +62,21 @@ static inline const struct file_operations *debugfs_real_fops(struct file *filp) return filp->f_path.dentry->d_fsdata; } +#define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ +static int __fops ## _open(struct inode *inode, struct file *file) \ +{ \ + __simple_attr_check_format(__fmt, 0ull); \ + return simple_attr_open(inode, file, __get, __set, __fmt); \ +} \ +static const struct file_operations __fops = { \ + .owner = THIS_MODULE, \ + .open = __fops ## _open, \ + .release = simple_attr_release, \ + .read = debugfs_attr_read, \ + .write = debugfs_attr_write, \ + .llseek = generic_file_llseek, \ +} + #if defined(CONFIG_DEBUG_FS) struct dentry *debugfs_create_file(const char *name, umode_t mode, @@ -99,21 +114,6 @@ ssize_t debugfs_attr_read(struct file *file, char __user *buf, ssize_t debugfs_attr_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos); -#define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ -static int __fops ## _open(struct inode *inode, struct file *file) \ -{ \ - __simple_attr_check_format(__fmt, 0ull); \ - return simple_attr_open(inode, file, __get, __set, __fmt); \ -} \ -static const struct file_operations __fops = { \ - .owner = THIS_MODULE, \ - .open = __fops ## _open, \ - .release = simple_attr_release, \ - .read = debugfs_attr_read, \ - .write = debugfs_attr_write, \ - .llseek = generic_file_llseek, \ -} - struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, struct dentry *new_dir, const char *new_name); @@ -233,8 +233,18 @@ static inline void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu) { } -#define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ - static const struct file_operations __fops = { 0 } +static inline ssize_t debugfs_attr_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos) +{ + return -ENODEV; +} + +static inline ssize_t debugfs_attr_write(struct file *file, + const char __user *buf, + size_t len, loff_t *ppos) +{ + return -ENODEV; +} static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, struct dentry *new_dir, char *new_name) -- cgit v1.2.3 From 9ed9895370aedd6032af2a9181c62c394d08223b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Oct 2016 17:32:16 +0100 Subject: driver core: Functional dependencies tracking support Currently, there is a problem with taking functional dependencies between devices into account. What I mean by a "functional dependency" is when the driver of device B needs device A to be functional and (generally) its driver to be present in order to work properly. This has certain consequences for power management (suspend/resume and runtime PM ordering) and shutdown ordering of these devices. In general, it also implies that the driver of A needs to be working for B to be probed successfully and it cannot be unbound from the device before the B's driver. Support for representing those functional dependencies between devices is added here to allow the driver core to track them and act on them in certain cases where applicable. The argument for doing that in the driver core is that there are quite a few distinct use cases involving device dependencies, they are relatively hard to get right in a driver (if one wants to address all of them properly) and it only gets worse if multiplied by the number of drivers potentially needing to do it. Morever, at least one case (asynchronous system suspend/resume) cannot be handled in a single driver at all, because it requires the driver of A to wait for B to suspend (during system suspend) and the driver of B to wait for A to resume (during system resume). For this reason, represent dependencies between devices as "links", with the help of struct device_link objects each containing pointers to the "linked" devices, a list node for each of them, status information, flags, and an RCU head for synchronization. Also add two new list heads, representing the lists of links to the devices that depend on the given one (consumers) and to the devices depended on by it (suppliers), and a "driver presence status" field (needed for figuring out initial states of device links) to struct device. The entire data structure consisting of all of the lists of link objects for all devices is protected by a mutex (for link object addition/removal and for list walks during device driver probing and removal) and by SRCU (for list walking in other case that will be introduced by subsequent change sets). If CONFIG_SRCU is not selected, however, an rwsem is used for protecting the entire data structure. In addition, each link object has an internal status field whose value reflects whether or not drivers are bound to the devices pointed to by the link or probing/removal of their drivers is in progress etc. That field is only modified under the device links mutex, but it may be read outside of it in some cases (introduced by subsequent change sets), so modifications of it are annotated with WRITE_ONCE(). New links are added by calling device_link_add() which takes three arguments: pointers to the devices in question and flags. In particular, if DL_FLAG_STATELESS is set in the flags, the link status is not to be taken into account for this link and the driver core will not manage it. In turn, if DL_FLAG_AUTOREMOVE is set in the flags, the driver core will remove the link automatically when the consumer device driver unbinds from it. One of the actions carried out by device_link_add() is to reorder the lists used for device shutdown and system suspend/resume to put the consumer device along with all of its children and all of its consumers (and so on, recursively) to the ends of those lists in order to ensure the right ordering between all of the supplier and consumer devices. For this reason, it is not possible to create a link between two devices if the would-be supplier device already depends on the would-be consumer device as either a direct descendant of it or a consumer of one of its direct descendants or one of its consumers and so on. There are two types of link objects, persistent and non-persistent. The persistent ones stay around until one of the target devices is deleted, while the non-persistent ones are removed automatically when the consumer driver unbinds from its device (ie. they are assumed to be valid only as long as the consumer device has a driver bound to it). Persistent links are created by default and non-persistent links are created when the DL_FLAG_AUTOREMOVE flag is passed to device_link_add(). Both persistent and non-persistent device links can be deleted with an explicit call to device_link_del(). Links created without the DL_FLAG_STATELESS flag set are managed by the driver core using a simple state machine. There are 5 states each link can be in: DORMANT (unused), AVAILABLE (the supplier driver is present and functional), CONSUMER_PROBE (the consumer driver is probing), ACTIVE (both supplier and consumer drivers are present and functional), and SUPPLIER_UNBIND (the supplier driver is unbinding). The driver core updates the link state automatically depending on what happens to the linked devices and for each link state specific actions are taken in addition to that. For example, if the supplier driver unbinds from its device, the driver core will also unbind the drivers of all of its consumers automatically under the assumption that they cannot function properly without the supplier. Analogously, the driver core will only allow the consumer driver to bind to its device if the supplier driver is present and functional (ie. the link is in the AVAILABLE state). If that's not the case, it will rely on the existing deferred probing mechanism to wait for the supplier driver to become available. Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/pm.h | 1 + 2 files changed, 81 insertions(+) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index bc41e87a969b..9cae2feaf5cb 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -707,6 +707,81 @@ struct device_dma_parameters { unsigned long segment_boundary_mask; }; +/** + * enum device_link_state - Device link states. + * @DL_STATE_NONE: The presence of the drivers is not being tracked. + * @DL_STATE_DORMANT: None of the supplier/consumer drivers is present. + * @DL_STATE_AVAILABLE: The supplier driver is present, but the consumer is not. + * @DL_STATE_CONSUMER_PROBE: The consumer is probing (supplier driver present). + * @DL_STATE_ACTIVE: Both the supplier and consumer drivers are present. + * @DL_STATE_SUPPLIER_UNBIND: The supplier driver is unbinding. + */ +enum device_link_state { + DL_STATE_NONE = -1, + DL_STATE_DORMANT = 0, + DL_STATE_AVAILABLE, + DL_STATE_CONSUMER_PROBE, + DL_STATE_ACTIVE, + DL_STATE_SUPPLIER_UNBIND, +}; + +/* + * Device link flags. + * + * STATELESS: The core won't track the presence of supplier/consumer drivers. + * AUTOREMOVE: Remove this link automatically on consumer driver unbind. + */ +#define DL_FLAG_STATELESS BIT(0) +#define DL_FLAG_AUTOREMOVE BIT(1) + +/** + * struct device_link - Device link representation. + * @supplier: The device on the supplier end of the link. + * @s_node: Hook to the supplier device's list of links to consumers. + * @consumer: The device on the consumer end of the link. + * @c_node: Hook to the consumer device's list of links to suppliers. + * @status: The state of the link (with respect to the presence of drivers). + * @flags: Link flags. + * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks. + */ +struct device_link { + struct device *supplier; + struct list_head s_node; + struct device *consumer; + struct list_head c_node; + enum device_link_state status; + u32 flags; +#ifdef CONFIG_SRCU + struct rcu_head rcu_head; +#endif +}; + +/** + * enum dl_dev_state - Device driver presence tracking information. + * @DL_DEV_NO_DRIVER: There is no driver attached to the device. + * @DL_DEV_PROBING: A driver is probing. + * @DL_DEV_DRIVER_BOUND: The driver has been bound to the device. + * @DL_DEV_UNBINDING: The driver is unbinding from the device. + */ +enum dl_dev_state { + DL_DEV_NO_DRIVER = 0, + DL_DEV_PROBING, + DL_DEV_DRIVER_BOUND, + DL_DEV_UNBINDING, +}; + +/** + * struct dev_links_info - Device data related to device links. + * @suppliers: List of links to supplier devices. + * @consumers: List of links to consumer devices. + * @status: Driver status information. + */ +struct dev_links_info { + struct list_head suppliers; + struct list_head consumers; + enum dl_dev_state status; +}; + /** * struct device - The basic device structure * @parent: The device's "parent" device, the device to which it is attached. @@ -799,6 +874,7 @@ struct device { core doesn't touch it */ void *driver_data; /* Driver data, set and get with dev_set/get_drvdata */ + struct dev_links_info links; struct dev_pm_info power; struct dev_pm_domain *pm_domain; @@ -1116,6 +1192,10 @@ extern void device_shutdown(void); /* debugging and troubleshooting/diagnostic helpers. */ extern const char *dev_driver_string(const struct device *dev); +/* Device links interface. */ +struct device_link *device_link_add(struct device *consumer, + struct device *supplier, u32 flags); +void device_link_del(struct device_link *link); #ifdef CONFIG_PRINTK diff --git a/include/linux/pm.h b/include/linux/pm.h index 06eb353182ab..721a70241fcd 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -559,6 +559,7 @@ struct dev_pm_info { pm_message_t power_state; unsigned int can_wakeup:1; unsigned int async_suspend:1; + bool in_dpm_list:1; /* Owned by the PM core */ bool is_prepared:1; /* Owned by the PM core */ bool is_suspended:1; /* Ditto */ bool is_noirq_suspended:1; -- cgit v1.2.3 From 21d5c57b3726166421251e94dabab047baaf8ce4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Oct 2016 17:32:31 +0100 Subject: PM / runtime: Use device links Modify the runtime PM framework to use device links to ensure that supplier devices will not be suspended if any of their consumer devices are active. The idea is to reference count suppliers on the consumer's resume and drop references to them on its suspend. The information on whether or not the supplier has been reference counted by the consumer's (runtime) resume is stored in a new field (rpm_active) in the link object for each link. It may be necessary to clean up those references when the supplier is unbinding and that's why the links whose status is DEVICE_LINK_SUPPLIER_UNBIND are skipped by the runtime suspend and resume code. The above means that if the consumer device is probed in the runtime-active state, the supplier has to be resumed and reference counted by device_link_add() so the code works as expected on its (runtime) suspend. There is a new flag, DEVICE_LINK_RPM_ACTIVE, to tell device_link_add() about that (in which case the caller is responsible for making sure that the consumer really will be runtime-active when runtime PM is enabled for it). The other new link flag, DEVICE_LINK_PM_RUNTIME, tells the core whether or not the link should be used for runtime PM at all. Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 6 ++++++ include/linux/pm_runtime.h | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'include') diff --git a/include/linux/device.h b/include/linux/device.h index 9cae2feaf5cb..49f453892ca5 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -730,9 +730,13 @@ enum device_link_state { * * STATELESS: The core won't track the presence of supplier/consumer drivers. * AUTOREMOVE: Remove this link automatically on consumer driver unbind. + * PM_RUNTIME: If set, the runtime PM framework will use this link. + * RPM_ACTIVE: Run pm_runtime_get_sync() on the supplier during link creation. */ #define DL_FLAG_STATELESS BIT(0) #define DL_FLAG_AUTOREMOVE BIT(1) +#define DL_FLAG_PM_RUNTIME BIT(2) +#define DL_FLAG_RPM_ACTIVE BIT(3) /** * struct device_link - Device link representation. @@ -742,6 +746,7 @@ enum device_link_state { * @c_node: Hook to the consumer device's list of links to suppliers. * @status: The state of the link (with respect to the presence of drivers). * @flags: Link flags. + * @rpm_active: Whether or not the consumer device is runtime-PM-active. * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks. */ struct device_link { @@ -751,6 +756,7 @@ struct device_link { struct list_head c_node; enum device_link_state status; u32 flags; + bool rpm_active; #ifdef CONFIG_SRCU struct rcu_head rcu_head; #endif diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 2e14d2667b6c..c2ee87138e4a 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -55,6 +55,9 @@ extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev); extern void pm_runtime_update_max_time_suspended(struct device *dev, s64 delta_ns); extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable); +extern void pm_runtime_clean_up_links(struct device *dev); +extern void pm_runtime_get_suppliers(struct device *dev); +extern void pm_runtime_put_suppliers(struct device *dev); static inline void pm_suspend_ignore_children(struct device *dev, bool enable) { @@ -186,6 +189,9 @@ static inline unsigned long pm_runtime_autosuspend_expiration( struct device *dev) { return 0; } static inline void pm_runtime_set_memalloc_noio(struct device *dev, bool enable){} +static inline void pm_runtime_clean_up_links(struct device *dev) {} +static inline void pm_runtime_get_suppliers(struct device *dev) {} +static inline void pm_runtime_put_suppliers(struct device *dev) {} #endif /* !CONFIG_PM */ -- cgit v1.2.3 From baa8809f60971d10220dfe79248f54b2b265f003 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Oct 2016 17:32:43 +0100 Subject: PM / runtime: Optimize the use of device links If the device has no links to suppliers that should be used for runtime PM (links with DEVICE_LINK_PM_RUNTIME set), there is no reason to walk the list of suppliers for that device during runtime suspend and resume. Add a simple mechanism to detect that case and possibly avoid the extra unnecessary overhead. Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- include/linux/pm.h | 1 + include/linux/pm_runtime.h | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/pm.h b/include/linux/pm.h index 721a70241fcd..ccfe00ecc7e6 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -597,6 +597,7 @@ struct dev_pm_info { unsigned int use_autosuspend:1; unsigned int timer_autosuspends:1; unsigned int memalloc_noio:1; + unsigned int links_count; enum rpm_request request; enum rpm_status runtime_status; int runtime_error; diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index c2ee87138e4a..73814877537d 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -58,6 +58,8 @@ extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable); extern void pm_runtime_clean_up_links(struct device *dev); extern void pm_runtime_get_suppliers(struct device *dev); extern void pm_runtime_put_suppliers(struct device *dev); +extern void pm_runtime_new_link(struct device *dev); +extern void pm_runtime_drop_link(struct device *dev); static inline void pm_suspend_ignore_children(struct device *dev, bool enable) { @@ -192,6 +194,8 @@ static inline void pm_runtime_set_memalloc_noio(struct device *dev, static inline void pm_runtime_clean_up_links(struct device *dev) {} static inline void pm_runtime_get_suppliers(struct device *dev) {} static inline void pm_runtime_put_suppliers(struct device *dev) {} +static inline void pm_runtime_new_link(struct device *dev) {} +static inline void pm_runtime_drop_link(struct device *dev) {} #endif /* !CONFIG_PM */ -- cgit v1.2.3 From fac51482577d5e05bbb0efa8d602a3c2111098bf Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 28 Oct 2016 09:45:28 +0100 Subject: drivers: base: cacheinfo: fix x86 with CONFIG_OF enabled With CONFIG_OF enabled on x86, we get the following error on boot: " Failed to find cpu0 device node Unable to detect cache hierarchy from DT for CPU 0 " and the cacheinfo fails to get populated in the corresponding sysfs entries. This is because cache_setup_of_node looks for of_node for setting up the shared cpu_map without checking that it's already populated in the architecture specific callback. In order to indicate that the shared cpu_map is already populated, this patch introduces a boolean `cpu_map_populated` in struct cpu_cacheinfo that can be used by the generic code to skip cache_shared_cpu_map_setup. This patch also sets that boolean for x86. Cc: Greg Kroah-Hartman Signed-off-by: Sudeep Holla Signed-off-by: Greg Kroah-Hartman --- include/linux/cacheinfo.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index 2189935075b4..a951fd10aaaa 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h @@ -71,6 +71,7 @@ struct cpu_cacheinfo { struct cacheinfo *info_list; unsigned int num_levels; unsigned int num_leaves; + bool cpu_map_populated; }; /* -- cgit v1.2.3 From 51f8cc9e818a9e6df376db7aeb5822d43e58cfb3 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Mon, 14 Nov 2016 12:16:26 +0000 Subject: iommu/dma: Implement dma_{map,unmap}_resource() With the new dma_{map,unmap}_resource() functions added to the DMA API for the benefit of cases like slave DMA, add suitable implementations to the arsenal of our generic layer. Since cache maintenance should not be a concern, these can both be standalone callback implementations without the need for arch code wrappers. CC: Joerg Roedel Signed-off-by: Robin Murphy Reviewed-by: Catalin Marinas Signed-off-by: Joerg Roedel --- include/linux/dma-iommu.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h index 32c589062bd9..7f7e9a7e3839 100644 --- a/include/linux/dma-iommu.h +++ b/include/linux/dma-iommu.h @@ -61,6 +61,10 @@ void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size, enum dma_data_direction dir, unsigned long attrs); void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir, unsigned long attrs); +dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys, + size_t size, enum dma_data_direction dir, unsigned long attrs); +void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle, + size_t size, enum dma_data_direction dir, unsigned long attrs); int iommu_dma_supported(struct device *dev, u64 mask); int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr); -- cgit v1.2.3 From 13f59a78c6d69a9bf4c8989dd5f3396f54a2fe41 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Fri, 11 Nov 2016 17:59:21 +0000 Subject: iommu: Allow taking a reference on a group directly iommu_group_get_for_dev() expects that the IOMMU driver's device_group callback return a group with a reference held for the given device. Whilst allocating a new group is fine, and pci_device_group() correctly handles reusing an existing group, there is no general means for IOMMU drivers doing their own group lookup to take additional references on an existing group pointer without having to also store device pointers or resort to elaborate trickery. Add an IOMMU-driver-specific function to fill the hole. Acked-by: Sricharan R Signed-off-by: Robin Murphy Signed-off-by: Joerg Roedel --- include/linux/iommu.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 436dc21318af..431638110c6a 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -253,6 +253,7 @@ extern void iommu_group_remove_device(struct device *dev); extern int iommu_group_for_each_dev(struct iommu_group *group, void *data, int (*fn)(struct device *, void *)); extern struct iommu_group *iommu_group_get(struct device *dev); +extern struct iommu_group *iommu_group_ref_get(struct iommu_group *group); extern void iommu_group_put(struct iommu_group *group); extern int iommu_group_register_notifier(struct iommu_group *group, struct notifier_block *nb); -- cgit v1.2.3 From 027b25b26447aaf597c8b7729dd3b1fbebc6d5e8 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 21 Nov 2016 10:01:33 +0000 Subject: ACPI: Add FWNODE_ACPI_STATIC fwnode type On systems booting with a device tree, every struct device is associated with a struct device_node, that provides its DT firmware representation. The device node can be used in generic kernel contexts (eg IRQ translation, IOMMU streamid mapping), to retrieve the properties associated with the device and carry out kernel operations accordingly. Owing to the 1:1 relationship between the device and its device_node, the device_node can also be used as a look-up token for the device (eg looking up a device through its device_node), to retrieve the device in kernel paths where the device_node is available. On systems booting with ACPI, the same abstraction provided by the device_node is required to provide look-up functionality. The struct acpi_device, that represents firmware objects in the ACPI namespace already includes a struct fwnode_handle of type FWNODE_ACPI as their member; the same abstraction is missing though for devices that are instantiated out of static ACPI tables entries (eg ARM SMMU devices). Add a new fwnode_handle type to associate devices created out of static ACPI table entries to the respective firmware components and create a simple ACPI core layer interface to dynamically allocate and free the corresponding firmware nodes so that kernel subsystems can use it to instantiate the nodes and associate them with the respective devices. Signed-off-by: Lorenzo Pieralisi Acked-by: Rafael J. Wysocki Reviewed-by: Hanjun Guo Reviewed-by: Tomasz Nowicki Tested-by: Hanjun Guo Tested-by: Tomasz Nowicki Cc: "Rafael J. Wysocki" Signed-off-by: Will Deacon --- include/linux/acpi.h | 21 +++++++++++++++++++++ include/linux/fwnode.h | 3 ++- 2 files changed, 23 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 61a3d90f32b3..996a29cdaccd 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -56,6 +56,27 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev) acpi_fwnode_handle(adev) : NULL) #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) +static inline struct fwnode_handle *acpi_alloc_fwnode_static(void) +{ + struct fwnode_handle *fwnode; + + fwnode = kzalloc(sizeof(struct fwnode_handle), GFP_KERNEL); + if (!fwnode) + return NULL; + + fwnode->type = FWNODE_ACPI_STATIC; + + return fwnode; +} + +static inline void acpi_free_fwnode_static(struct fwnode_handle *fwnode) +{ + if (WARN_ON(!fwnode || fwnode->type != FWNODE_ACPI_STATIC)) + return; + + kfree(fwnode); +} + /** * ACPI_DEVICE_CLASS - macro used to describe an ACPI device with * the PCI-defined class-code information diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index 851671742790..8bd28ce6d76e 100644 --- a/include/linux/fwnode.h +++ b/include/linux/fwnode.h @@ -17,8 +17,9 @@ enum fwnode_type { FWNODE_OF, FWNODE_ACPI, FWNODE_ACPI_DATA, + FWNODE_ACPI_STATIC, FWNODE_PDATA, - FWNODE_IRQCHIP, + FWNODE_IRQCHIP }; struct fwnode_handle { -- cgit v1.2.3 From 34ceea275f626ae624b55f2b388a07f806988a55 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 21 Nov 2016 10:01:34 +0000 Subject: ACPI/IORT: Introduce linker section for IORT entries probing Since commit e647b532275b ("ACPI: Add early device probing infrastructure") the kernel has gained the infrastructure that allows adding linker script section entries to execute ACPI driver callbacks (ie probe routines) for all subsystems that register a table entry in the respective kernel section (eg clocksource, irqchip). Since ARM IOMMU devices data is described through IORT tables when booting with ACPI, the ARM IOMMU drivers must be made able to hook ACPI callback routines that are called to probe IORT entries and initialize the respective IOMMU devices. To avoid adding driver specific hooks into IORT table initialization code (breaking therefore code modularity - ie ACPI IORT code must be made aware of ARM SMMU drivers ACPI init callbacks), this patch adds code that allows ARM SMMU drivers to take advantage of the ACPI early probing infrastructure, so that they can add linker script section entries containing drivers callback to be executed on IORT tables detection. Since IORT nodes are differentiated by a type, the callback routines can easily parse the IORT table entries, check the IORT nodes and carry out some actions whenever the IORT node type associated with the driver specific callback is matched. Signed-off-by: Lorenzo Pieralisi Reviewed-by: Hanjun Guo Reviewed-by: Tomasz Nowicki Tested-by: Hanjun Guo Tested-by: Tomasz Nowicki Cc: Tomasz Nowicki Cc: "Rafael J. Wysocki" Cc: Marc Zyngier Signed-off-by: Will Deacon --- include/asm-generic/vmlinux.lds.h | 1 + include/linux/acpi_iort.h | 3 +++ 2 files changed, 4 insertions(+) (limited to 'include') diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 31e1d639abed..9e3aa34341f4 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -566,6 +566,7 @@ IRQCHIP_OF_MATCH_TABLE() \ ACPI_PROBE_TABLE(irqchip) \ ACPI_PROBE_TABLE(clksrc) \ + ACPI_PROBE_TABLE(iort) \ EARLYCON_TABLE() #define INIT_TEXT \ diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h index 0e32dac8fd03..d16fddaf230e 100644 --- a/include/linux/acpi_iort.h +++ b/include/linux/acpi_iort.h @@ -39,4 +39,7 @@ static inline struct irq_domain *iort_get_device_domain(struct device *dev, { return NULL; } #endif +#define IORT_ACPI_DECLARE(name, table_id, fn) \ + ACPI_DECLARE_PROBE_ENTRY(iort, name, table_id, 0, NULL, 0, fn) + #endif /* __ACPI_IORT_H__ */ -- cgit v1.2.3 From e4f10ffe4c9b500e545b874b816ffea5e8659b05 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 21 Nov 2016 10:01:36 +0000 Subject: iommu: Make of_iommu_set/get_ops() DT agnostic The of_iommu_{set/get}_ops() API is used to associate a device tree node with a specific set of IOMMU operations. The same kernel interface is required on systems booting with ACPI, where devices are not associated with a device tree node, therefore the interface requires generalization. The struct device fwnode member represents the fwnode token associated with the device and the struct it points at is firmware specific; regardless, it is initialized on both ACPI and DT systems and makes an ideal candidate to use it to associate a set of IOMMU operations to a given device, through its struct device.fwnode member pointer, paving the way for representing per-device iommu_ops (ie an iommu instance associated with a device). Convert the DT specific of_iommu_{set/get}_ops() interface to use struct device.fwnode as a look-up token, making the interface usable on ACPI systems and rename the data structures and the registration API so that they are made to represent their usage more clearly. Signed-off-by: Lorenzo Pieralisi Acked-by: Will Deacon Reviewed-by: Robin Murphy Reviewed-by: Tomasz Nowicki Tested-by: Hanjun Guo Tested-by: Tomasz Nowicki Cc: Will Deacon Cc: Hanjun Guo Cc: Robin Murphy Cc: Joerg Roedel Signed-off-by: Will Deacon --- include/linux/iommu.h | 14 ++++++++++++++ include/linux/of_iommu.h | 12 ++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 436dc21318af..f2960e4de344 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -351,6 +351,9 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, const struct iommu_ops *ops); void iommu_fwspec_free(struct device *dev); int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids); +void iommu_register_instance(struct fwnode_handle *fwnode, + const struct iommu_ops *ops); +const struct iommu_ops *iommu_get_instance(struct fwnode_handle *fwnode); #else /* CONFIG_IOMMU_API */ @@ -580,6 +583,17 @@ static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids, return -ENODEV; } +static inline void iommu_register_instance(struct fwnode_handle *fwnode, + const struct iommu_ops *ops) +{ +} + +static inline +const struct iommu_ops *iommu_get_instance(struct fwnode_handle *fwnode) +{ + return NULL; +} + #endif /* CONFIG_IOMMU_API */ #endif /* __LINUX_IOMMU_H */ diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index e80b9c762a03..6a7fc5051099 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -31,8 +31,16 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev, #endif /* CONFIG_OF_IOMMU */ -void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops); -const struct iommu_ops *of_iommu_get_ops(struct device_node *np); +static inline void of_iommu_set_ops(struct device_node *np, + const struct iommu_ops *ops) +{ + iommu_register_instance(&np->fwnode, ops); +} + +static inline const struct iommu_ops *of_iommu_get_ops(struct device_node *np) +{ + return iommu_get_instance(&np->fwnode); +} extern struct of_device_id __iommu_of_table; -- cgit v1.2.3 From d760a1baf20e067d3a063aa134834ddd3d183e2f Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 21 Nov 2016 10:01:39 +0000 Subject: ACPI: Implement acpi_dma_configure On DT based systems, the of_dma_configure() API implements DMA configuration for a given device. On ACPI systems an API equivalent to of_dma_configure() is missing which implies that it is currently not possible to set-up DMA operations for devices through the ACPI generic kernel layer. This patch fills the gap by introducing acpi_dma_configure/deconfigure() calls that for now are just wrappers around arch_setup_dma_ops() and arch_teardown_dma_ops() and also updates ACPI and PCI core code to use the newly introduced acpi_dma_configure/acpi_dma_deconfigure functions. Since acpi_dma_configure() is used to configure DMA operations, the function initializes the dma/coherent_dma masks to sane default values if the current masks are uninitialized (also to keep the default values consistent with DT systems) to make sure the device has a complete default DMA set-up. The DMA range size passed to arch_setup_dma_ops() is sized according to the device coherent_dma_mask (starting at address 0x0), mirroring the DT probing path behaviour when a dma-ranges property is not provided for the device being probed; this changes the current arch_setup_dma_ops() call parameters in the ACPI probing case, but since arch_setup_dma_ops() is a NOP on all architectures but ARM/ARM64 this patch does not change the current kernel behaviour on them. Signed-off-by: Lorenzo Pieralisi Acked-by: Bjorn Helgaas [pci] Acked-by: Rafael J. Wysocki Reviewed-by: Tomasz Nowicki Tested-by: Hanjun Guo Tested-by: Tomasz Nowicki Cc: Bjorn Helgaas Cc: Robin Murphy Cc: Tomasz Nowicki Cc: Joerg Roedel Cc: "Rafael J. Wysocki" Signed-off-by: Will Deacon --- include/acpi/acpi_bus.h | 2 ++ include/linux/acpi.h | 5 +++++ 2 files changed, 7 insertions(+) (limited to 'include') diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index c1a524de67c5..4242c31ffaee 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -573,6 +573,8 @@ struct acpi_pci_root { bool acpi_dma_supported(struct acpi_device *adev); enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev); +void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr); +void acpi_dma_deconfigure(struct device *dev); struct acpi_device *acpi_find_child_device(struct acpi_device *parent, u64 address, bool check_children); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 996a29cdaccd..8d15fc59719f 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -765,6 +765,11 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev) return DEV_DMA_NOT_SUPPORTED; } +static inline void acpi_dma_configure(struct device *dev, + enum dev_dma_attr attr) { } + +static inline void acpi_dma_deconfigure(struct device *dev) { } + #define ACPI_PTR(_ptr) (NULL) static inline void acpi_device_set_enumerated(struct acpi_device *adev) -- cgit v1.2.3 From bdca0c077fc5c2a7bb405281263270070c67f917 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 21 Nov 2016 10:01:40 +0000 Subject: ACPI/IORT: Add node match function Device drivers (eg ARM SMMU) need to know if a specific component is part of the IORT table, so that kernel data structures are not initialized at initcalls time if the respective component is not part of the IORT table. To this end, this patch adds a trivial function that allows detecting if a given IORT node type is present or not in the ACPI table, providing an ACPI IORT equivalent for of_find_matching_node(). Signed-off-by: Lorenzo Pieralisi Reviewed-by: Tomasz Nowicki Tested-by: Hanjun Guo Tested-by: Tomasz Nowicki Acked-by: Hanjun Guo Cc: Hanjun Guo Cc: Tomasz Nowicki Cc: "Rafael J. Wysocki" Signed-off-by: Will Deacon --- include/linux/acpi_iort.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h index d16fddaf230e..17bb078073de 100644 --- a/include/linux/acpi_iort.h +++ b/include/linux/acpi_iort.h @@ -28,10 +28,12 @@ void iort_deregister_domain_token(int trans_id); struct fwnode_handle *iort_find_domain_token(int trans_id); #ifdef CONFIG_ACPI_IORT void acpi_iort_init(void); +bool iort_node_match(u8 type); u32 iort_msi_map_rid(struct device *dev, u32 req_id); struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id); #else static inline void acpi_iort_init(void) { } +static inline bool iort_node_match(u8 type) { return false; } static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id) { return req_id; } static inline struct irq_domain *iort_get_device_domain(struct device *dev, -- cgit v1.2.3 From d6fcd3b149f3eab3b94cc107ca846bea8461cc2f Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 21 Nov 2016 10:01:45 +0000 Subject: iommu/arm-smmu: Add IORT configuration In ACPI based systems, in order to be able to create platform devices and initialize them for ARM SMMU components, the IORT kernel implementation requires a set of static functions to be used by the IORT kernel layer to configure platform devices for ARM SMMU components. Add static configuration functions to the IORT kernel layer for the ARM SMMU components, so that the ARM SMMU driver can initialize its respective platform device by relying on the IORT kernel infrastructure and by adding a corresponding ACPI device early probe section entry. Signed-off-by: Lorenzo Pieralisi Reviewed-by: Tomasz Nowicki Tested-by: Hanjun Guo Tested-by: Tomasz Nowicki Cc: Will Deacon Cc: Robin Murphy Cc: Joerg Roedel Signed-off-by: Will Deacon --- include/linux/acpi_iort.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h index 17bb078073de..79ba1bb50950 100644 --- a/include/linux/acpi_iort.h +++ b/include/linux/acpi_iort.h @@ -23,6 +23,9 @@ #include #include +#define IORT_IRQ_MASK(irq) (irq & 0xffffffffULL) +#define IORT_IRQ_TRIGGER_MASK(irq) ((irq >> 32) & 0xffffffffULL) + int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node); void iort_deregister_domain_token(int trans_id); struct fwnode_handle *iort_find_domain_token(int trans_id); -- cgit v1.2.3 From 643b8e4d86f8b1a62cf5cd9ea221e9bc0d531d18 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 21 Nov 2016 10:01:48 +0000 Subject: ACPI/IORT: Introduce iort_iommu_configure DT based systems have a generic kernel API to configure IOMMUs for devices (ie of_iommu_configure()). On ARM based ACPI systems, the of_iommu_configure() equivalent can be implemented atop ACPI IORT kernel API, with the corresponding functions to map device identifiers to IOMMUs and retrieve the corresponding IOMMU operations necessary for DMA operations set-up. By relying on the iommu_fwspec generic kernel infrastructure, implement the IORT based IOMMU configuration for ARM ACPI systems and hook it up in the ACPI kernel layer that implements DMA configuration for a device. Signed-off-by: Lorenzo Pieralisi Acked-by: Rafael J. Wysocki [ACPI core] Reviewed-by: Tomasz Nowicki Tested-by: Hanjun Guo Tested-by: Tomasz Nowicki Cc: Hanjun Guo Cc: Tomasz Nowicki Cc: "Rafael J. Wysocki" Signed-off-by: Will Deacon --- include/linux/acpi_iort.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h index 79ba1bb50950..dcb2b601e152 100644 --- a/include/linux/acpi_iort.h +++ b/include/linux/acpi_iort.h @@ -34,6 +34,8 @@ void acpi_iort_init(void); bool iort_node_match(u8 type); u32 iort_msi_map_rid(struct device *dev, u32 req_id); struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id); +/* IOMMU interface */ +const struct iommu_ops *iort_iommu_configure(struct device *dev); #else static inline void acpi_iort_init(void) { } static inline bool iort_node_match(u8 type) { return false; } @@ -42,6 +44,10 @@ static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id) static inline struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id) { return NULL; } +/* IOMMU interface */ +static inline +const struct iommu_ops *iort_iommu_configure(struct device *dev) +{ return NULL; } #endif #define IORT_ACPI_DECLARE(name, table_id, fn) \ -- cgit v1.2.3 From 18b709beb503bfc9a96a2e4b93d3cae4f5b17df0 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Tue, 6 Dec 2016 14:20:11 +0000 Subject: ACPI/IORT: Make dma masks set-up IORT specific The introduction of acpi_dma_configure() allows to configure DMA and related IOMMU for any device that is DMA capable. To achieve that goal it ensures DMA masks are set-up to sane default values before proceeding with IOMMU and DMA ops configuration. On x86/ia64 systems, through acpi_bind_one(), acpi_dma_configure() is called for every device that has an ACPI companion, in that every device is considered DMA capable on x86/ia64 systems (ie acpi_get_dma_attr() API), which has the side effect of initializing dma masks also for pseudo-devices (eg CPUs and memory nodes) and potentially for devices whose dma masks were not set-up before the acpi_dma_configure() API was introduced, which may have noxious side effects. Therefore, in preparation for IORT firmware specific DMA masks set-up, wrap the default DMA masks set-up in acpi_dma_configure() inside an IORT specific wrapper that reverts to a NOP on x86/ia64 systems, restoring the default expected behaviour on x86/ia64 systems and keeping DMA default masks set-up on IORT based (ie ARM) arch configurations. Signed-off-by: Lorenzo Pieralisi Acked-by: Will Deacon Acked-by: Rafael J. Wysocki Reviewed-by: Hanjun Guo Tested-by: Hanjun Guo Cc: Will Deacon Cc: Hanjun Guo Cc: Bjorn Helgaas Cc: Robin Murphy Cc: Tomasz Nowicki Cc: Joerg Roedel Cc: "Rafael J. Wysocki" Cc: Sricharan R Signed-off-by: Joerg Roedel --- include/linux/acpi_iort.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h index dcb2b601e152..77e08099e554 100644 --- a/include/linux/acpi_iort.h +++ b/include/linux/acpi_iort.h @@ -35,6 +35,7 @@ bool iort_node_match(u8 type); u32 iort_msi_map_rid(struct device *dev, u32 req_id); struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id); /* IOMMU interface */ +void iort_set_dma_mask(struct device *dev); const struct iommu_ops *iort_iommu_configure(struct device *dev); #else static inline void acpi_iort_init(void) { } @@ -45,6 +46,7 @@ static inline struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id) { return NULL; } /* IOMMU interface */ +static inline void iort_set_dma_mask(struct device *dev) { } static inline const struct iommu_ops *iort_iommu_configure(struct device *dev) { return NULL; } -- cgit v1.2.3