|
@@ -821,27 +821,65 @@ static inline bool is_zone_device_page(const struct page *page)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-#if defined(CONFIG_DEVICE_PRIVATE) || defined(CONFIG_DEVICE_PUBLIC)
|
|
|
-void put_zone_device_private_or_public_page(struct page *page);
|
|
|
-DECLARE_STATIC_KEY_FALSE(device_private_key);
|
|
|
-#define IS_HMM_ENABLED static_branch_unlikely(&device_private_key)
|
|
|
-static inline bool is_device_private_page(const struct page *page);
|
|
|
-static inline bool is_device_public_page(const struct page *page);
|
|
|
-#else /* CONFIG_DEVICE_PRIVATE || CONFIG_DEVICE_PUBLIC */
|
|
|
-static inline void put_zone_device_private_or_public_page(struct page *page)
|
|
|
+#ifdef CONFIG_DEV_PAGEMAP_OPS
|
|
|
+void dev_pagemap_get_ops(void);
|
|
|
+void dev_pagemap_put_ops(void);
|
|
|
+void __put_devmap_managed_page(struct page *page);
|
|
|
+DECLARE_STATIC_KEY_FALSE(devmap_managed_key);
|
|
|
+static inline bool put_devmap_managed_page(struct page *page)
|
|
|
+{
|
|
|
+ if (!static_branch_unlikely(&devmap_managed_key))
|
|
|
+ return false;
|
|
|
+ if (!is_zone_device_page(page))
|
|
|
+ return false;
|
|
|
+ switch (page->pgmap->type) {
|
|
|
+ case MEMORY_DEVICE_PRIVATE:
|
|
|
+ case MEMORY_DEVICE_PUBLIC:
|
|
|
+ case MEMORY_DEVICE_FS_DAX:
|
|
|
+ __put_devmap_managed_page(page);
|
|
|
+ return true;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+static inline bool is_device_private_page(const struct page *page)
|
|
|
{
|
|
|
+ return is_zone_device_page(page) &&
|
|
|
+ page->pgmap->type == MEMORY_DEVICE_PRIVATE;
|
|
|
}
|
|
|
-#define IS_HMM_ENABLED 0
|
|
|
+
|
|
|
+static inline bool is_device_public_page(const struct page *page)
|
|
|
+{
|
|
|
+ return is_zone_device_page(page) &&
|
|
|
+ page->pgmap->type == MEMORY_DEVICE_PUBLIC;
|
|
|
+}
|
|
|
+
|
|
|
+#else /* CONFIG_DEV_PAGEMAP_OPS */
|
|
|
+static inline void dev_pagemap_get_ops(void)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+static inline void dev_pagemap_put_ops(void)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+static inline bool put_devmap_managed_page(struct page *page)
|
|
|
+{
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
static inline bool is_device_private_page(const struct page *page)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
static inline bool is_device_public_page(const struct page *page)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
-#endif /* CONFIG_DEVICE_PRIVATE || CONFIG_DEVICE_PUBLIC */
|
|
|
-
|
|
|
+#endif /* CONFIG_DEV_PAGEMAP_OPS */
|
|
|
|
|
|
static inline void get_page(struct page *page)
|
|
|
{
|
|
@@ -859,16 +897,13 @@ static inline void put_page(struct page *page)
|
|
|
page = compound_head(page);
|
|
|
|
|
|
/*
|
|
|
- * For private device pages we need to catch refcount transition from
|
|
|
- * 2 to 1, when refcount reach one it means the private device page is
|
|
|
- * free and we need to inform the device driver through callback. See
|
|
|
+ * For devmap managed pages we need to catch refcount transition from
|
|
|
+ * 2 to 1, when refcount reach one it means the page is free and we
|
|
|
+ * need to inform the device driver through callback. See
|
|
|
* include/linux/memremap.h and HMM for details.
|
|
|
*/
|
|
|
- if (IS_HMM_ENABLED && unlikely(is_device_private_page(page) ||
|
|
|
- unlikely(is_device_public_page(page)))) {
|
|
|
- put_zone_device_private_or_public_page(page);
|
|
|
+ if (put_devmap_managed_page(page))
|
|
|
return;
|
|
|
- }
|
|
|
|
|
|
if (put_page_testzero(page))
|
|
|
__put_page(page);
|