drm/amd/display: Proper return of result when aux engine acquire fails
[linux-2.6-microblaze.git] / block / bio.c
index ce797d7..299a0e7 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/workqueue.h>
 #include <linux/cgroup.h>
 #include <linux/blk-cgroup.h>
+#include <linux/highmem.h>
 
 #include <trace/events/block.h>
 #include "blk.h"
@@ -558,14 +559,6 @@ void bio_put(struct bio *bio)
 }
 EXPORT_SYMBOL(bio_put);
 
-int bio_phys_segments(struct request_queue *q, struct bio *bio)
-{
-       if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
-               blk_recount_segments(q, bio);
-
-       return bio->bi_phys_segments;
-}
-
 /**
  *     __bio_clone_fast - clone a bio that shares the original bio's biovec
  *     @bio: destination bio
@@ -731,10 +724,10 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio,
                }
        }
 
-       if (bio_full(bio))
+       if (bio_full(bio, len))
                return 0;
 
-       if (bio->bi_phys_segments >= queue_max_segments(q))
+       if (bio->bi_vcnt >= queue_max_segments(q))
                return 0;
 
        bvec = &bio->bi_io_vec[bio->bi_vcnt];
@@ -744,8 +737,6 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio,
        bio->bi_vcnt++;
  done:
        bio->bi_iter.bi_size += len;
-       bio->bi_phys_segments = bio->bi_vcnt;
-       bio_set_flag(bio, BIO_SEG_VALID);
        return len;
 }
 
@@ -807,7 +798,7 @@ void __bio_add_page(struct bio *bio, struct page *page,
        struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt];
 
        WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED));
-       WARN_ON_ONCE(bio_full(bio));
+       WARN_ON_ONCE(bio_full(bio, len));
 
        bv->bv_page = page;
        bv->bv_offset = off;
@@ -834,7 +825,7 @@ int bio_add_page(struct bio *bio, struct page *page,
        bool same_page = false;
 
        if (!__bio_try_merge_page(bio, page, len, offset, &same_page)) {
-               if (bio_full(bio))
+               if (bio_full(bio, len))
                        return 0;
                __bio_add_page(bio, page, len, offset);
        }
@@ -842,22 +833,19 @@ int bio_add_page(struct bio *bio, struct page *page,
 }
 EXPORT_SYMBOL(bio_add_page);
 
-static void bio_get_pages(struct bio *bio)
+void bio_release_pages(struct bio *bio, bool mark_dirty)
 {
        struct bvec_iter_all iter_all;
        struct bio_vec *bvec;
 
-       bio_for_each_segment_all(bvec, bio, iter_all)
-               get_page(bvec->bv_page);
-}
-
-static void bio_release_pages(struct bio *bio)
-{
-       struct bvec_iter_all iter_all;
-       struct bio_vec *bvec;
+       if (bio_flagged(bio, BIO_NO_PAGE_REF))
+               return;
 
-       bio_for_each_segment_all(bvec, bio, iter_all)
+       bio_for_each_segment_all(bvec, bio, iter_all) {
+               if (mark_dirty && !PageCompound(bvec->bv_page))
+                       set_page_dirty_lock(bvec->bv_page);
                put_page(bvec->bv_page);
+       }
 }
 
 static int __bio_iov_bvec_add_pages(struct bio *bio, struct iov_iter *iter)
@@ -922,7 +910,7 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
                        if (same_page)
                                put_page(page);
                } else {
-                       if (WARN_ON_ONCE(bio_full(bio)))
+                       if (WARN_ON_ONCE(bio_full(bio, len)))
                                 return -EINVAL;
                        __bio_add_page(bio, page, len, offset);
                }
@@ -966,13 +954,10 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
                        ret = __bio_iov_bvec_add_pages(bio, iter);
                else
                        ret = __bio_iov_iter_get_pages(bio, iter);
-       } while (!ret && iov_iter_count(iter) && !bio_full(bio));
+       } while (!ret && iov_iter_count(iter) && !bio_full(bio, 0));
 
-       if (iov_iter_bvec_no_ref(iter))
+       if (is_bvec)
                bio_set_flag(bio, BIO_NO_PAGE_REF);
-       else if (is_bvec)
-               bio_get_pages(bio);
-
        return bio->bi_vcnt ? 0 : ret;
 }
 
@@ -1124,8 +1109,7 @@ static struct bio_map_data *bio_alloc_map_data(struct iov_iter *data,
        if (data->nr_segs > UIO_MAXIOV)
                return NULL;
 
-       bmd = kmalloc(sizeof(struct bio_map_data) +
-                      sizeof(struct iovec) * data->nr_segs, gfp_mask);
+       bmd = kmalloc(struct_size(bmd, iov, data->nr_segs), gfp_mask);
        if (!bmd)
                return NULL;
        memcpy(bmd->iov, data->iov, sizeof(struct iovec) * data->nr_segs);
@@ -1371,8 +1355,6 @@ struct bio *bio_map_user_iov(struct request_queue *q,
        int j;
        struct bio *bio;
        int ret;
-       struct bio_vec *bvec;
-       struct bvec_iter_all iter_all;
 
        if (!iov_iter_count(iter))
                return ERR_PTR(-EINVAL);
@@ -1439,31 +1421,11 @@ struct bio *bio_map_user_iov(struct request_queue *q,
        return bio;
 
  out_unmap:
-       bio_for_each_segment_all(bvec, bio, iter_all) {
-               put_page(bvec->bv_page);
-       }
+       bio_release_pages(bio, false);
        bio_put(bio);
        return ERR_PTR(ret);
 }
 
-static void __bio_unmap_user(struct bio *bio)
-{
-       struct bio_vec *bvec;
-       struct bvec_iter_all iter_all;
-
-       /*
-        * make sure we dirty pages we wrote to
-        */
-       bio_for_each_segment_all(bvec, bio, iter_all) {
-               if (bio_data_dir(bio) == READ)
-                       set_page_dirty_lock(bvec->bv_page);
-
-               put_page(bvec->bv_page);
-       }
-
-       bio_put(bio);
-}
-
 /**
  *     bio_unmap_user  -       unmap a bio
  *     @bio:           the bio being unmapped
@@ -1475,12 +1437,27 @@ static void __bio_unmap_user(struct bio *bio)
  */
 void bio_unmap_user(struct bio *bio)
 {
-       __bio_unmap_user(bio);
+       bio_release_pages(bio, bio_data_dir(bio) == READ);
+       bio_put(bio);
        bio_put(bio);
 }
 
+static void bio_invalidate_vmalloc_pages(struct bio *bio)
+{
+#ifdef ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
+       if (bio->bi_private && !op_is_write(bio_op(bio))) {
+               unsigned long i, len = 0;
+
+               for (i = 0; i < bio->bi_vcnt; i++)
+                       len += bio->bi_io_vec[i].bv_len;
+               invalidate_kernel_vmap_range(bio->bi_private, len);
+       }
+#endif
+}
+
 static void bio_map_kern_endio(struct bio *bio)
 {
+       bio_invalidate_vmalloc_pages(bio);
        bio_put(bio);
 }
 
@@ -1501,6 +1478,8 @@ struct bio *bio_map_kern(struct request_queue *q, void *data, unsigned int len,
        unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
        unsigned long start = kaddr >> PAGE_SHIFT;
        const int nr_pages = end - start;
+       bool is_vmalloc = is_vmalloc_addr(data);
+       struct page *page;
        int offset, i;
        struct bio *bio;
 
@@ -1508,6 +1487,11 @@ struct bio *bio_map_kern(struct request_queue *q, void *data, unsigned int len,
        if (!bio)
                return ERR_PTR(-ENOMEM);
 
+       if (is_vmalloc) {
+               flush_kernel_vmap_range(data, len);
+               bio->bi_private = data;
+       }
+
        offset = offset_in_page(kaddr);
        for (i = 0; i < nr_pages; i++) {
                unsigned int bytes = PAGE_SIZE - offset;
@@ -1518,7 +1502,11 @@ struct bio *bio_map_kern(struct request_queue *q, void *data, unsigned int len,
                if (bytes > len)
                        bytes = len;
 
-               if (bio_add_pc_page(q, bio, virt_to_page(data), bytes,
+               if (!is_vmalloc)
+                       page = virt_to_page(data);
+               else
+                       page = vmalloc_to_page(data);
+               if (bio_add_pc_page(q, bio, page, bytes,
                                    offset) < bytes) {
                        /* we don't support partial mappings */
                        bio_put(bio);
@@ -1695,9 +1683,7 @@ static void bio_dirty_fn(struct work_struct *work)
        while ((bio = next) != NULL) {
                next = bio->bi_private;
 
-               bio_set_pages_dirty(bio);
-               if (!bio_flagged(bio, BIO_NO_PAGE_REF))
-                       bio_release_pages(bio);
+               bio_release_pages(bio, true);
                bio_put(bio);
        }
 }
@@ -1713,8 +1699,7 @@ void bio_check_pages_dirty(struct bio *bio)
                        goto defer;
        }
 
-       if (!bio_flagged(bio, BIO_NO_PAGE_REF))
-               bio_release_pages(bio);
+       bio_release_pages(bio, false);
        bio_put(bio);
        return;
 defer:
@@ -1775,18 +1760,6 @@ void generic_end_io_acct(struct request_queue *q, int req_op,
 }
 EXPORT_SYMBOL(generic_end_io_acct);
 
-#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
-void bio_flush_dcache_pages(struct bio *bi)
-{
-       struct bio_vec bvec;
-       struct bvec_iter iter;
-
-       bio_for_each_segment(bvec, bi, iter)
-               flush_dcache_page(bvec.bv_page);
-}
-EXPORT_SYMBOL(bio_flush_dcache_pages);
-#endif
-
 static inline bool bio_remaining_done(struct bio *bio)
 {
        /*
@@ -1914,10 +1887,7 @@ void bio_trim(struct bio *bio, int offset, int size)
        if (offset == 0 && size == bio->bi_iter.bi_size)
                return;
 
-       bio_clear_flag(bio, BIO_SEG_VALID);
-
        bio_advance(bio, offset << 9);
-
        bio->bi_iter.bi_size = size;
 
        if (bio_integrity(bio))