genirq: Dont allow affinity mask to be updated on IPIs
[linux-2.6-block.git] / kernel / memremap.c
index 584febd13e2e3864a336c66998c69f85480d4211..a6d382312e6f3ff2cdb0bb526f8bbd2978ebffc1 100644 (file)
@@ -41,11 +41,13 @@ static void *try_ram_remap(resource_size_t offset, size_t size)
  * memremap() - remap an iomem_resource as cacheable memory
  * @offset: iomem resource start address
  * @size: size of remap
- * @flags: either MEMREMAP_WB or MEMREMAP_WT
+ * @flags: any of MEMREMAP_WB, MEMREMAP_WT and MEMREMAP_WC
  *
  * memremap() is "ioremap" for cases where it is known that the resource
  * being mapped does not have i/o side effects and the __iomem
- * annotation is not applicable.
+ * annotation is not applicable. In the case of multiple flags, the different
+ * mapping types will be attempted in the order listed below until one of
+ * them succeeds.
  *
  * MEMREMAP_WB - matches the default mapping for System RAM on
  * the architecture.  This is usually a read-allocate write-back cache.
@@ -57,6 +59,10 @@ static void *try_ram_remap(resource_size_t offset, size_t size)
  * cache or are written through to memory and never exist in a
  * cache-dirty state with respect to program visibility.  Attempts to
  * map System RAM with this mapping type will fail.
+ *
+ * MEMREMAP_WC - establish a writecombine mapping, whereby writes may
+ * be coalesced together (e.g. in the CPU's write buffers), but is otherwise
+ * uncached. Attempts to map System RAM with this mapping type will fail.
  */
 void *memremap(resource_size_t offset, size_t size, unsigned long flags)
 {
@@ -64,6 +70,9 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
                                       IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
        void *addr = NULL;
 
+       if (!flags)
+               return NULL;
+
        if (is_ram == REGION_MIXED) {
                WARN_ONCE(1, "memremap attempted on mixed range %pa size: %#lx\n",
                                &offset, (unsigned long) size);
@@ -72,7 +81,6 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
 
        /* Try all mapping types requested until one returns non-NULL */
        if (flags & MEMREMAP_WB) {
-               flags &= ~MEMREMAP_WB;
                /*
                 * MEMREMAP_WB is special in that it can be satisifed
                 * from the direct map.  Some archs depend on the
@@ -86,21 +94,22 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
        }
 
        /*
-        * If we don't have a mapping yet and more request flags are
-        * pending then we will be attempting to establish a new virtual
+        * If we don't have a mapping yet and other request flags are
+        * present then we will be attempting to establish a new virtual
         * address mapping.  Enforce that this mapping is not aliasing
         * System RAM.
         */
-       if (!addr && is_ram == REGION_INTERSECTS && flags) {
+       if (!addr && is_ram == REGION_INTERSECTS && flags != MEMREMAP_WB) {
                WARN_ONCE(1, "memremap attempted on ram %pa size: %#lx\n",
                                &offset, (unsigned long) size);
                return NULL;
        }
 
-       if (!addr && (flags & MEMREMAP_WT)) {
-               flags &= ~MEMREMAP_WT;
+       if (!addr && (flags & MEMREMAP_WT))
                addr = ioremap_wt(offset, size);
-       }
+
+       if (!addr && (flags & MEMREMAP_WC))
+               addr = ioremap_wc(offset, size);
 
        return addr;
 }