OSDN Git Service

powerpc/pseries: Allow not having ibm, hypertas-functions::hcall-multi-tce for DDW
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / fs / pstore / ram_core.c
index 76c3f80..679d75a 100644 (file)
@@ -48,48 +48,14 @@ static inline size_t buffer_start(struct persistent_ram_zone *prz)
 }
 
 /* increase and wrap the start pointer, returning the old value */
-static size_t buffer_start_add_atomic(struct persistent_ram_zone *prz, size_t a)
+static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
 {
        int old;
        int new;
+       unsigned long flags = 0;
 
-       do {
-               old = atomic_read(&prz->buffer->start);
-               new = old + a;
-               while (unlikely(new >= prz->buffer_size))
-                       new -= prz->buffer_size;
-       } while (atomic_cmpxchg(&prz->buffer->start, old, new) != old);
-
-       return old;
-}
-
-/* increase the size counter until it hits the max size */
-static void buffer_size_add_atomic(struct persistent_ram_zone *prz, size_t a)
-{
-       size_t old;
-       size_t new;
-
-       if (atomic_read(&prz->buffer->size) == prz->buffer_size)
-               return;
-
-       do {
-               old = atomic_read(&prz->buffer->size);
-               new = old + a;
-               if (new > prz->buffer_size)
-                       new = prz->buffer_size;
-       } while (atomic_cmpxchg(&prz->buffer->size, old, new) != old);
-}
-
-static DEFINE_RAW_SPINLOCK(buffer_lock);
-
-/* increase and wrap the start pointer, returning the old value */
-static size_t buffer_start_add_locked(struct persistent_ram_zone *prz, size_t a)
-{
-       int old;
-       int new;
-       unsigned long flags;
-
-       raw_spin_lock_irqsave(&buffer_lock, flags);
+       if (!(prz->flags & PRZ_FLAG_NO_LOCK))
+               raw_spin_lock_irqsave(&prz->buffer_lock, flags);
 
        old = atomic_read(&prz->buffer->start);
        new = old + a;
@@ -97,19 +63,21 @@ static size_t buffer_start_add_locked(struct persistent_ram_zone *prz, size_t a)
                new -= prz->buffer_size;
        atomic_set(&prz->buffer->start, new);
 
-       raw_spin_unlock_irqrestore(&buffer_lock, flags);
+       if (!(prz->flags & PRZ_FLAG_NO_LOCK))
+               raw_spin_unlock_irqrestore(&prz->buffer_lock, flags);
 
        return old;
 }
 
 /* increase the size counter until it hits the max size */
-static void buffer_size_add_locked(struct persistent_ram_zone *prz, size_t a)
+static void buffer_size_add(struct persistent_ram_zone *prz, size_t a)
 {
        size_t old;
        size_t new;
-       unsigned long flags;
+       unsigned long flags = 0;
 
-       raw_spin_lock_irqsave(&buffer_lock, flags);
+       if (!(prz->flags & PRZ_FLAG_NO_LOCK))
+               raw_spin_lock_irqsave(&prz->buffer_lock, flags);
 
        old = atomic_read(&prz->buffer->size);
        if (old == prz->buffer_size)
@@ -121,12 +89,10 @@ static void buffer_size_add_locked(struct persistent_ram_zone *prz, size_t a)
        atomic_set(&prz->buffer->size, new);
 
 exit:
-       raw_spin_unlock_irqrestore(&buffer_lock, flags);
+       if (!(prz->flags & PRZ_FLAG_NO_LOCK))
+               raw_spin_unlock_irqrestore(&prz->buffer_lock, flags);
 }
 
-static size_t (*buffer_start_add)(struct persistent_ram_zone *, size_t) = buffer_start_add_atomic;
-static void (*buffer_size_add)(struct persistent_ram_zone *, size_t) = buffer_size_add_atomic;
-
 static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz,
        uint8_t *data, size_t len, uint8_t *ecc)
 {
@@ -299,7 +265,7 @@ static void notrace persistent_ram_update(struct persistent_ram_zone *prz,
        const void *s, unsigned int start, unsigned int count)
 {
        struct persistent_ram_buffer *buffer = prz->buffer;
-       memcpy(buffer->data + start, s, count);
+       memcpy_toio(buffer->data + start, s, count);
        persistent_ram_update_ecc(prz, start, count);
 }
 
@@ -322,8 +288,8 @@ void persistent_ram_save_old(struct persistent_ram_zone *prz)
        }
 
        prz->old_log_size = size;
-       memcpy(prz->old_log, &buffer->data[start], size - start);
-       memcpy(prz->old_log + size - start, &buffer->data[0], start);
+       memcpy_fromio(prz->old_log, &buffer->data[start], size - start);
+       memcpy_fromio(prz->old_log + size - start, &buffer->data[0], start);
 }
 
 int notrace persistent_ram_write(struct persistent_ram_zone *prz,
@@ -412,7 +378,12 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size,
        vaddr = vmap(pages, page_count, VM_MAP, prot);
        kfree(pages);
 
-       return vaddr;
+       /*
+        * Since vmap() uses page granularity, we must add the offset
+        * into the page here, to get the byte granularity address
+        * into the mapping to represent the actual "start" location.
+        */
+       return vaddr + offset_in_page(start);
 }
 
 static void *persistent_ram_iomap(phys_addr_t start, size_t size,
@@ -426,14 +397,16 @@ static void *persistent_ram_iomap(phys_addr_t start, size_t size,
                return NULL;
        }
 
-       buffer_start_add = buffer_start_add_locked;
-       buffer_size_add = buffer_size_add_locked;
-
        if (memtype)
                va = ioremap(start, size);
        else
                va = ioremap_wc(start, size);
 
+       /*
+        * Since request_mem_region() and ioremap() are byte-granularity
+        * there is no need handle anything special like we do when the
+        * vmap() case in persistent_ram_vmap() above.
+        */
        return va;
 }
 
@@ -454,7 +427,7 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
                return -ENOMEM;
        }
 
-       prz->buffer = prz->vaddr + offset_in_page(start);
+       prz->buffer = prz->vaddr;
        prz->buffer_size = size - sizeof(struct persistent_ram_buffer);
 
        return 0;
@@ -472,6 +445,11 @@ static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig,
        sig ^= PERSISTENT_RAM_SIG;
 
        if (prz->buffer->sig == sig) {
+               if (buffer_size(prz) == 0) {
+                       pr_debug("found existing empty buffer\n");
+                       return 0;
+               }
+
                if (buffer_size(prz) > prz->buffer_size ||
                    buffer_start(prz) > buffer_size(prz))
                        pr_info("found existing invalid buffer, size %zu, start %zu\n",
@@ -487,6 +465,7 @@ static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig,
                         prz->buffer->sig);
        }
 
+       /* Rewind missing or invalid memory area. */
        prz->buffer->sig = sig;
        persistent_ram_zap(prz);
 
@@ -500,7 +479,8 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
 
        if (prz->vaddr) {
                if (pfn_valid(prz->paddr >> PAGE_SHIFT)) {
-                       vunmap(prz->vaddr);
+                       /* We must vunmap() at page-granularity. */
+                       vunmap(prz->vaddr - offset_in_page(prz->paddr));
                } else {
                        iounmap(prz->vaddr);
                        release_mem_region(prz->paddr, prz->size);
@@ -513,7 +493,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
 
 struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
                        u32 sig, struct persistent_ram_ecc_info *ecc_info,
-                       unsigned int memtype)
+                       unsigned int memtype, u32 flags)
 {
        struct persistent_ram_zone *prz;
        int ret = -ENOMEM;
@@ -524,6 +504,10 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
                goto err;
        }
 
+       /* Initialize general buffer state. */
+       raw_spin_lock_init(&prz->buffer_lock);
+       prz->flags = flags;
+
        ret = persistent_ram_buffer_map(start, size, prz, memtype);
        if (ret)
                goto err;