diff mbox

[V1,net-next,1/2] pgtable: Add API to query if write combining is available

Message ID 1412497342-12451-2-git-send-email-ogerlitz@mellanox.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Or Gerlitz Oct. 5, 2014, 8:22 a.m. UTC
From: Moshe Lazer <moshel@mellanox.com>

Currently the kernel write-combining interface provides a best effort
mechanism in which the caller simply invokes pgprot_writecombine().

If write combining is available, the region is mapped for it, otherwise
the region is (silently) mapped as non-cached.

In some cases, however, the calling driver must know if write combining
is available, so a silent best effort mechanism is not sufficient.

Add writecombine_available(), which returns true if the system
supports write combining and false if it doesn't.

Signed-off-by: Moshe Lazer <moshel@mellanox.com>
Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
 arch/arm/include/asm/pgtable.h       |    6 ++++++
 arch/arm64/include/asm/pgtable.h     |    5 +++++
 arch/ia64/include/asm/pgtable.h      |    6 ++++++
 arch/powerpc/include/asm/pgtable.h   |    6 ++++++
 arch/x86/include/asm/pgtable_types.h |    2 ++
 arch/x86/mm/pat.c                    |    9 +++++++++
 include/asm-generic/pgtable.h        |    8 ++++++++
 7 files changed, 42 insertions(+), 0 deletions(-)

Comments

David Miller Oct. 7, 2014, 7:44 p.m. UTC | #1
From: Or Gerlitz <ogerlitz@mellanox.com>
Date: Sun,  5 Oct 2014 11:22:21 +0300

> From: Moshe Lazer <moshel@mellanox.com>
> 
> Currently the kernel write-combining interface provides a best effort
> mechanism in which the caller simply invokes pgprot_writecombine().
> 
> If write combining is available, the region is mapped for it, otherwise
> the region is (silently) mapped as non-cached.
> 
> In some cases, however, the calling driver must know if write combining
> is available, so a silent best effort mechanism is not sufficient.
> 
> Add writecombine_available(), which returns true if the system
> supports write combining and false if it doesn't.
> 
> Signed-off-by: Moshe Lazer <moshel@mellanox.com>
> Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>

This needs some ACKs from MM developers.

But also the situation is more complicated than a simple boolean test.

On some platforms you have to test first whether the range you are
trying to write combine can legally be marked in that way.  The DRM
layer has all of these per-arch tests to do this properly.

#if defined(__i386__) || defined(__x86_64__)
	if (map->type == _DRM_REGISTERS && !(map->flags & _DRM_WRITE_COMBINING))
		tmp = pgprot_noncached(tmp);
	else
		tmp = pgprot_writecombine(tmp);
#elif defined(__powerpc__)
	pgprot_val(tmp) |= _PAGE_NO_CACHE;
	if (map->type == _DRM_REGISTERS)
		pgprot_val(tmp) |= _PAGE_GUARDED;
#elif defined(__ia64__)
	if (efi_range_is_wc(vma->vm_start, vma->vm_end -
				    vma->vm_start))
		tmp = pgprot_writecombine(tmp);
	else
		tmp = pgprot_noncached(tmp);
#elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
	tmp = pgprot_noncached(tmp);
#endif
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Moshe Lazer Oct. 8, 2014, 8:44 a.m. UTC | #2
> From: David Miller [mailto:davem@davemloft.net]
> Sent: Tuesday, October 07, 2014 10:44 PM
> To: Or Gerlitz
> Cc: netdev@vger.kernel.org; Amir Vadai; jackm@dev.mellanox.co.il; Moshe Lazer; Tal Alon; Yevgeny Petrilin
> Subject: Re: [PATCH V1 net-next 1/2] pgtable: Add API to query if write combining is available
>
> From: Or Gerlitz <ogerlitz@mellanox.com>
> Date: Sun,  5 Oct 2014 11:22:21 +0300
>
>> From: Moshe Lazer <moshel@mellanox.com>
>>
>> Currently the kernel write-combining interface provides a best effort
>> mechanism in which the caller simply invokes pgprot_writecombine().
>>
>> If write combining is available, the region is mapped for it,
>> otherwise the region is (silently) mapped as non-cached.
>>
>> In some cases, however, the calling driver must know if write
>> combining is available, so a silent best effort mechanism is not sufficient.
>>
>> Add writecombine_available(), which returns true if the system
>> supports write combining and false if it doesn't.
>>
>> Signed-off-by: Moshe Lazer <moshel@mellanox.com>
>> Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
>> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
> This needs some ACKs from MM developers.
>
> But also the situation is more complicated than a simple boolean test.
>
> On some platforms you have to test first whether the range you are trying to write combine can legally be marked in that way.  The DRM layer has all of these per-arch tests to do this properly.
>
> #if defined(__i386__) || defined(__x86_64__)
> 	if (map->type == _DRM_REGISTERS && !(map->flags & _DRM_WRITE_COMBINING))
> 		tmp = pgprot_noncached(tmp);
> 	else
> 		tmp = pgprot_writecombine(tmp);
> #elif defined(__powerpc__)
> 	pgprot_val(tmp) |= _PAGE_NO_CACHE;
> 	if (map->type == _DRM_REGISTERS)
> 		pgprot_val(tmp) |= _PAGE_GUARDED;
> #elif defined(__ia64__)
> 	if (efi_range_is_wc(vma->vm_start, vma->vm_end -
> 				    vma->vm_start))
> 		tmp = pgprot_writecombine(tmp);
> 	else
> 		tmp = pgprot_noncached(tmp);
> #elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
> 	tmp = pgprot_noncached(tmp);
> #endif
The idea was to provide an indication as for whether the arch supports 
write-combining in general.
If we want to benefit from blue flame operations, we need to map the 
blue flame registers as write combining - otherwise there is no benefit. 
So we would like to know if write combining is supported by the system 
or not.

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Laight Oct. 8, 2014, 8:50 a.m. UTC | #3
From: Moshe Lazer
> > From: David Miller [mailto:davem@davemloft.net]
> > Sent: Tuesday, October 07, 2014 10:44 PM
> > To: Or Gerlitz
> > Cc: netdev@vger.kernel.org; Amir Vadai; jackm@dev.mellanox.co.il; Moshe Lazer; Tal Alon; Yevgeny
> Petrilin
> > Subject: Re: [PATCH V1 net-next 1/2] pgtable: Add API to query if write combining is available
> >
> > From: Or Gerlitz <ogerlitz@mellanox.com>
> > Date: Sun,  5 Oct 2014 11:22:21 +0300
> >
> >> From: Moshe Lazer <moshel@mellanox.com>
> >>
> >> Currently the kernel write-combining interface provides a best effort
> >> mechanism in which the caller simply invokes pgprot_writecombine().
> >>
> >> If write combining is available, the region is mapped for it,
> >> otherwise the region is (silently) mapped as non-cached.
> >>
> >> In some cases, however, the calling driver must know if write
> >> combining is available, so a silent best effort mechanism is not sufficient.
> >>
> >> Add writecombine_available(), which returns true if the system
> >> supports write combining and false if it doesn't.
> >>
> >> Signed-off-by: Moshe Lazer <moshel@mellanox.com>
> >> Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
> >> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
> > This needs some ACKs from MM developers.
> >
> > But also the situation is more complicated than a simple boolean test.
> >
> > On some platforms you have to test first whether the range you are trying to write combine can
> legally be marked in that way.  The DRM layer has all of these per-arch tests to do this properly.
> >
> > #if defined(__i386__) || defined(__x86_64__)
> > 	if (map->type == _DRM_REGISTERS && !(map->flags & _DRM_WRITE_COMBINING))
> > 		tmp = pgprot_noncached(tmp);
> > 	else
> > 		tmp = pgprot_writecombine(tmp);
> > #elif defined(__powerpc__)
> > 	pgprot_val(tmp) |= _PAGE_NO_CACHE;
> > 	if (map->type == _DRM_REGISTERS)
> > 		pgprot_val(tmp) |= _PAGE_GUARDED;
> > #elif defined(__ia64__)
> > 	if (efi_range_is_wc(vma->vm_start, vma->vm_end -
> > 				    vma->vm_start))
> > 		tmp = pgprot_writecombine(tmp);
> > 	else
> > 		tmp = pgprot_noncached(tmp);
> > #elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
> > 	tmp = pgprot_noncached(tmp);
> > #endif

> The idea was to provide an indication as for whether the arch supports
> write-combining in general.
> If we want to benefit from blue flame operations, we need to map the
> blue flame registers as write combining - otherwise there is no benefit.
> So we would like to know if write combining is supported by the system
> or not.

Sounds like the mapping functions should have a mode where 'write combining'
is mandatory, then you can try to map the registers as 'write combining' and
if the map request fails use the alternate scheme.

That moves the test into the architecture specific mapping code where
it belongs.

	David



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller Oct. 8, 2014, 4:24 p.m. UTC | #4
From: Moshe Lazer <moshel@dev.mellanox.co.il>
Date: Wed, 08 Oct 2014 11:44:57 +0300

>> #if defined(__i386__) || defined(__x86_64__)
>> 	if (map->type == _DRM_REGISTERS && !(map->flags & _DRM_WRITE_COMBINING))
>> 		tmp = pgprot_noncached(tmp);
>> 	else
>> 		tmp = pgprot_writecombine(tmp);
>> #elif defined(__powerpc__)
>> 	pgprot_val(tmp) |= _PAGE_NO_CACHE;
>> 	if (map->type == _DRM_REGISTERS)
>> 		pgprot_val(tmp) |= _PAGE_GUARDED;
>> #elif defined(__ia64__)
>> 	if (efi_range_is_wc(vma->vm_start, vma->vm_end -
>> 				    vma->vm_start))
>> 		tmp = pgprot_writecombine(tmp);
>> 	else
>> 		tmp = pgprot_noncached(tmp);
>> #elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
>> 	tmp = pgprot_noncached(tmp);
>> #endif
> The idea was to provide an indication as for whether the arch supports
> write-combining in general.
> If we want to benefit from blue flame operations, we need to map the
> blue flame registers as write combining - otherwise there is no
> benefit. So we would like to know if write combining is supported by
> the system or not.
> 

You completely miss my point.  On a given architectuire it might be
_illegal_ to map certain address ranges as write-combining without
checks like the ones above that ia64 needs.

Therefore your proposed interface is by definition insufficient.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Moshe Lazer Oct. 12, 2014, 9:54 a.m. UTC | #5
On 10/8/2014 7:24 PM, David Miller wrote:
> From: Moshe Lazer <moshel@dev.mellanox.co.il>
> Date: Wed, 08 Oct 2014 11:44:57 +0300
>
>>> #if defined(__i386__) || defined(__x86_64__)
>>> 	if (map->type == _DRM_REGISTERS && !(map->flags & _DRM_WRITE_COMBINING))
>>> 		tmp = pgprot_noncached(tmp);
>>> 	else
>>> 		tmp = pgprot_writecombine(tmp);
>>> #elif defined(__powerpc__)
>>> 	pgprot_val(tmp) |= _PAGE_NO_CACHE;
>>> 	if (map->type == _DRM_REGISTERS)
>>> 		pgprot_val(tmp) |= _PAGE_GUARDED;
>>> #elif defined(__ia64__)
>>> 	if (efi_range_is_wc(vma->vm_start, vma->vm_end -
>>> 				    vma->vm_start))
>>> 		tmp = pgprot_writecombine(tmp);
>>> 	else
>>> 		tmp = pgprot_noncached(tmp);
>>> #elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
>>> 	tmp = pgprot_noncached(tmp);
>>> #endif
>> The idea was to provide an indication as for whether the arch supports
>> write-combining in general.
>> If we want to benefit from blue flame operations, we need to map the
>> blue flame registers as write combining - otherwise there is no
>> benefit. So we would like to know if write combining is supported by
>> the system or not.
>>
> You completely miss my point.  On a given architectuire it might be
> _illegal_ to map certain address ranges as write-combining without
> checks like the ones above that ia64 needs.
>
> Therefore your proposed interface is by definition insufficient.
Thanks David, I'll try to clarify my point.
For me the writecombine_available() is a way to know if the 
pgprot_writecombine() is effective or just cover call to the 
pgprot_noncached().
I want to use the writecombine_available() regardless to the mapping 
address.
For example in mlx4 query_device I want to indicate that blue-flame is 
not supported if  `writecombine_available() ==  false`.
In this case we don't have the mapping address yet.

Later on if an arch has write-combining (writecombine_available() ==  
true) when we try to map the blue-flame registers (in mlx4_ib_mmap):

     vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);

     if (io_remap_pfn_range(vma, vma->vm_start,
         to_mucontext(context)->uar.pfn +
         dev->dev->caps.num_uars,
         PAGE_SIZE, vma->vm_page_prot))
             return -EAGAIN;

I can be sure that pgprot_writecombine() is not a cover for 
pgprot_noncached().
The address checks that you mentioned should be part of 
io_remap_pfn_range, this function should fail if the vma->vm_start is 
not compatible to the vma->vm_page_prot.
Please let me know if I misunderstood something.

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Moshe Lazer Oct. 26, 2014, 3 p.m. UTC | #6
On 10/12/2014 12:54 PM, Moshe Lazer wrote:
>
> On 10/8/2014 7:24 PM, David Miller wrote:
>> From: Moshe Lazer <moshel@dev.mellanox.co.il>
>> Date: Wed, 08 Oct 2014 11:44:57 +0300
>>
>>>> #if defined(__i386__) || defined(__x86_64__)
>>>>     if (map->type == _DRM_REGISTERS && !(map->flags & 
>>>> _DRM_WRITE_COMBINING))
>>>>         tmp = pgprot_noncached(tmp);
>>>>     else
>>>>         tmp = pgprot_writecombine(tmp);
>>>> #elif defined(__powerpc__)
>>>>     pgprot_val(tmp) |= _PAGE_NO_CACHE;
>>>>     if (map->type == _DRM_REGISTERS)
>>>>         pgprot_val(tmp) |= _PAGE_GUARDED;
>>>> #elif defined(__ia64__)
>>>>     if (efi_range_is_wc(vma->vm_start, vma->vm_end -
>>>>                     vma->vm_start))
>>>>         tmp = pgprot_writecombine(tmp);
>>>>     else
>>>>         tmp = pgprot_noncached(tmp);
>>>> #elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
>>>>     tmp = pgprot_noncached(tmp);
>>>> #endif
>>> The idea was to provide an indication as for whether the arch supports
>>> write-combining in general.
>>> If we want to benefit from blue flame operations, we need to map the
>>> blue flame registers as write combining - otherwise there is no
>>> benefit. So we would like to know if write combining is supported by
>>> the system or not.
>>>
>> You completely miss my point.  On a given architectuire it might be
>> _illegal_ to map certain address ranges as write-combining without
>> checks like the ones above that ia64 needs.
>>
>> Therefore your proposed interface is by definition insufficient.
> Thanks Dave, I'll try to clarify my point.
> For me the writecombine_available() is a way to know if the 
> pgprot_writecombine() is effective or just cover call to the 
> pgprot_noncached().
> I want to use the writecombine_available() regardless to the mapping 
> address.
> For example in mlx4 query_device I want to indicate that blue-flame is 
> not supported if  `writecombine_available() == false`.
> In this case we don't have the mapping address yet.
>
> Later on if an arch has write-combining (writecombine_available() ==  
> true) when we try to map the blue-flame registers (in mlx4_ib_mmap):
>
>     vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
>
>     if (io_remap_pfn_range(vma, vma->vm_start,
>         to_mucontext(context)->uar.pfn +
>         dev->dev->caps.num_uars,
>         PAGE_SIZE, vma->vm_page_prot))
>             return -EAGAIN;
>
> I can be sure that pgprot_writecombine() is not a cover for 
> pgprot_noncached().
> The address checks that you mentioned should be part of 
> io_remap_pfn_range, this function should fail if the vma->vm_start is 
> not compatible to the vma->vm_page_prot.
> Please let me know if I misunderstood something.
>
Dave, is this clears my point or I still missing something?

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Or Gerlitz Nov. 27, 2014, 6:48 a.m. UTC | #7
On Sun, Oct 12, 2014 at 11:54 AM, Moshe Lazer <moshel@dev.mellanox.co.il> wrote:
>
> On 10/8/2014 7:24 PM, David Miller wrote:
>>
>> From: Moshe Lazer <moshel@dev.mellanox.co.il>
>> Date: Wed, 08 Oct 2014 11:44:57 +0300
>>
>>>> #if defined(__i386__) || defined(__x86_64__)
>>>>         if (map->type == _DRM_REGISTERS && !(map->flags &
>>>> _DRM_WRITE_COMBINING))
>>>>                 tmp = pgprot_noncached(tmp);
>>>>         else
>>>>                 tmp = pgprot_writecombine(tmp);
>>>> #elif defined(__powerpc__)
>>>>         pgprot_val(tmp) |= _PAGE_NO_CACHE;
>>>>         if (map->type == _DRM_REGISTERS)
>>>>                 pgprot_val(tmp) |= _PAGE_GUARDED;
>>>> #elif defined(__ia64__)
>>>>         if (efi_range_is_wc(vma->vm_start, vma->vm_end -
>>>>                                     vma->vm_start))
>>>>                 tmp = pgprot_writecombine(tmp);
>>>>         else
>>>>                 tmp = pgprot_noncached(tmp);
>>>> #elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
>>>>         tmp = pgprot_noncached(tmp);
>>>> #endif
>>>
>>> The idea was to provide an indication as for whether the arch supports
>>> write-combining in general.
>>> If we want to benefit from blue flame operations, we need to map the
>>> blue flame registers as write combining - otherwise there is no
>>> benefit. So we would like to know if write combining is supported by
>>> the system or not.
>>>
>> You completely miss my point.  On a given architectuire it might be
>> _illegal_ to map certain address ranges as write-combining without
>> checks like the ones above that ia64 needs.
>>
>> Therefore your proposed interface is by definition insufficient.
>
> Thanks David, I'll try to clarify my point.
> For me the writecombine_available() is a way to know if the
> pgprot_writecombine() is effective or just cover call to the
> pgprot_noncached().
> I want to use the writecombine_available() regardless to the mapping
> address.
> For example in mlx4 query_device I want to indicate that blue-flame is not
> supported if  `writecombine_available() ==  false`.
> In this case we don't have the mapping address yet.
>
> Later on if an arch has write-combining (writecombine_available() ==  true)
> when we try to map the blue-flame registers (in mlx4_ib_mmap):
>
>     vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
>
>     if (io_remap_pfn_range(vma, vma->vm_start,
>         to_mucontext(context)->uar.pfn +
>         dev->dev->caps.num_uars,
>         PAGE_SIZE, vma->vm_page_prot))
>             return -EAGAIN;
>
> I can be sure that pgprot_writecombine() is not a cover for
> pgprot_noncached().
> The address checks that you mentioned should be part of io_remap_pfn_range,
> this function should fail if the vma->vm_start is not compatible to the
> vma->vm_page_prot.
> Please let me know if I misunderstood something.


Hi Dave,

Pinging you... could you respond on Moshe's email which hopefully
addresses your comments?

Or.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller Dec. 12, 2014, 8:36 p.m. UTC | #8
From: Or Gerlitz <gerlitz.or@gmail.com>
Date: Thu, 27 Nov 2014 08:48:24 +0200

> On Sun, Oct 12, 2014 at 11:54 AM, Moshe Lazer <moshel@dev.mellanox.co.il> wrote:
>>
>> On 10/8/2014 7:24 PM, David Miller wrote:
>>>
>>> From: Moshe Lazer <moshel@dev.mellanox.co.il>
>>> Date: Wed, 08 Oct 2014 11:44:57 +0300
>>>
>>>>> #if defined(__i386__) || defined(__x86_64__)
>>>>>         if (map->type == _DRM_REGISTERS && !(map->flags &
>>>>> _DRM_WRITE_COMBINING))
>>>>>                 tmp = pgprot_noncached(tmp);
>>>>>         else
>>>>>                 tmp = pgprot_writecombine(tmp);
>>>>> #elif defined(__powerpc__)
>>>>>         pgprot_val(tmp) |= _PAGE_NO_CACHE;
>>>>>         if (map->type == _DRM_REGISTERS)
>>>>>                 pgprot_val(tmp) |= _PAGE_GUARDED;
>>>>> #elif defined(__ia64__)
>>>>>         if (efi_range_is_wc(vma->vm_start, vma->vm_end -
>>>>>                                     vma->vm_start))
>>>>>                 tmp = pgprot_writecombine(tmp);
>>>>>         else
>>>>>                 tmp = pgprot_noncached(tmp);
>>>>> #elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
>>>>>         tmp = pgprot_noncached(tmp);
>>>>> #endif
>>>>
>>>> The idea was to provide an indication as for whether the arch supports
>>>> write-combining in general.
>>>> If we want to benefit from blue flame operations, we need to map the
>>>> blue flame registers as write combining - otherwise there is no
>>>> benefit. So we would like to know if write combining is supported by
>>>> the system or not.
>>>>
>>> You completely miss my point.  On a given architectuire it might be
>>> _illegal_ to map certain address ranges as write-combining without
>>> checks like the ones above that ia64 needs.
>>>
>>> Therefore your proposed interface is by definition insufficient.
>>
>> Thanks David, I'll try to clarify my point.
>> For me the writecombine_available() is a way to know if the
>> pgprot_writecombine() is effective or just cover call to the
>> pgprot_noncached().
>> I want to use the writecombine_available() regardless to the mapping
>> address.
>> For example in mlx4 query_device I want to indicate that blue-flame is not
>> supported if  `writecombine_available() ==  false`.
>> In this case we don't have the mapping address yet.
 ...
> Pinging you... could you respond on Moshe's email which hopefully
> addresses your comments?

As I stated, some platforms have restrictions on certain address ranges
when it comes to supporting write combining.

Therefore, it is a _requirement_, not optional, that we have an
address available so that the platform specific code can give an
accurate response to the question "is write combining available"
because the answer to that question is address dependent.

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 01baef0..ce06b64 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -119,6 +119,12 @@  extern pgprot_t		pgprot_s2_device;
 #define pgprot_writecombine(prot) \
 	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
 
+#define writecombine_available writecombine_available
+static inline bool writecombine_available(void)
+{
+	return true;
+}
+
 #define pgprot_stronglyordered(prot) \
 	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
 
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index ffe1ba0..6ab0630 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -296,6 +296,11 @@  static inline int has_transparent_hugepage(void)
 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN)
 #define pgprot_writecombine(prot) \
 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN)
+#define writecombine_available writecombine_available
+static inline bool writecombine_available(void)
+{
+	return true;
+}
 #define __HAVE_PHYS_MEM_ACCESS_PROT
 struct file;
 extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
diff --git a/arch/ia64/include/asm/pgtable.h b/arch/ia64/include/asm/pgtable.h
index 7935115..2e44501 100644
--- a/arch/ia64/include/asm/pgtable.h
+++ b/arch/ia64/include/asm/pgtable.h
@@ -356,6 +356,12 @@  static inline void set_pte(pte_t *ptep, pte_t pteval)
 #define pgprot_noncached(prot)		__pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_UC)
 #define pgprot_writecombine(prot)	__pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WC)
 
+#define writecombine_available writecombine_available
+static inline bool writecombine_available(void)
+{
+	return true;
+}
+
 struct file;
 extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 				     unsigned long size, pgprot_t vma_prot);
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
index d98c1ec..3232d98 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -267,6 +267,12 @@  extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addre
 
 #define pgprot_writecombine pgprot_noncached_wc
 
+#define writecombine_available writecombine_available
+static inline bool writecombine_available(void)
+{
+	return true;
+}
+
 struct file;
 extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 				     unsigned long size, pgprot_t vma_prot);
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index f216963..7d3dc79 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -337,6 +337,8 @@  extern int nx_enabled;
 
 #define pgprot_writecombine	pgprot_writecombine
 extern pgprot_t pgprot_writecombine(pgprot_t prot);
+#define writecombine_available  writecombine_available
+bool writecombine_available(void);
 
 /* Indicate that x86 has its own track and untrack pfn vma functions */
 #define __HAVE_PFNMAP_TRACKING
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 6574388..851ee51 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -797,6 +797,15 @@  pgprot_t pgprot_writecombine(pgprot_t prot)
 }
 EXPORT_SYMBOL_GPL(pgprot_writecombine);
 
+bool writecombine_available(void)
+{
+	if (pat_enabled)
+		return true;
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(writecombine_available);
+
 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT)
 
 static struct memtype *memtype_get_idx(loff_t pos)
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 53b2acc..2cb40d9 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -249,6 +249,14 @@  static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
 #define pgprot_writecombine pgprot_noncached
 #endif
 
+#ifndef writecombine_available
+#define writecombine_available writecombine_available
+static inline bool writecombine_available(void)
+{
+	return false;
+}
+#endif
+
 /*
  * When walking page tables, get the address of the next boundary,
  * or the end address of the range if that comes earlier.  Although no