firmware: Factor out the paged buffer handling code
[linux-2.6-block.git] / drivers / base / firmware_loader / fallback.c
index 29becea1910dfb781e063c7fe15b3c3fcd2d26b7..62ee90b4db56e9ae30f5f17d365db1b2af67cd88 100644 (file)
@@ -219,25 +219,6 @@ static ssize_t firmware_loading_show(struct device *dev,
        return sprintf(buf, "%d\n", loading);
 }
 
-/* one pages buffer should be mapped/unmapped only once */
-static int map_fw_priv_pages(struct fw_priv *fw_priv)
-{
-       if (!fw_priv->pages)
-               return 0;
-
-       vunmap(fw_priv->data);
-       fw_priv->data = vmap(fw_priv->pages, fw_priv->nr_pages, 0,
-                            PAGE_KERNEL_RO);
-       if (!fw_priv->data)
-               return -ENOMEM;
-
-       /* page table is no longer needed after mapping, let's free */
-       kvfree(fw_priv->pages);
-       fw_priv->pages = NULL;
-
-       return 0;
-}
-
 /**
  * firmware_loading_store() - set value in the 'loading' control file
  * @dev: device pointer
@@ -283,7 +264,7 @@ static ssize_t firmware_loading_store(struct device *dev,
                         * see the mapped 'buf->data' once the loading
                         * is completed.
                         * */
-                       rc = map_fw_priv_pages(fw_priv);
+                       rc = fw_map_paged_buf(fw_priv);
                        if (rc)
                                dev_err(dev, "%s: map pages failed\n",
                                        __func__);
@@ -388,41 +369,13 @@ out:
 
 static int fw_realloc_pages(struct fw_sysfs *fw_sysfs, int min_size)
 {
-       struct fw_priv *fw_priv= fw_sysfs->fw_priv;
-       int pages_needed = PAGE_ALIGN(min_size) >> PAGE_SHIFT;
-
-       /* If the array of pages is too small, grow it... */
-       if (fw_priv->page_array_size < pages_needed) {
-               int new_array_size = max(pages_needed,
-                                        fw_priv->page_array_size * 2);
-               struct page **new_pages;
+       int err;
 
-               new_pages = kvmalloc_array(new_array_size, sizeof(void *),
-                                          GFP_KERNEL);
-               if (!new_pages) {
-                       fw_load_abort(fw_sysfs);
-                       return -ENOMEM;
-               }
-               memcpy(new_pages, fw_priv->pages,
-                      fw_priv->page_array_size * sizeof(void *));
-               memset(&new_pages[fw_priv->page_array_size], 0, sizeof(void *) *
-                      (new_array_size - fw_priv->page_array_size));
-               kvfree(fw_priv->pages);
-               fw_priv->pages = new_pages;
-               fw_priv->page_array_size = new_array_size;
-       }
-
-       while (fw_priv->nr_pages < pages_needed) {
-               fw_priv->pages[fw_priv->nr_pages] =
-                       alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
-
-               if (!fw_priv->pages[fw_priv->nr_pages]) {
-                       fw_load_abort(fw_sysfs);
-                       return -ENOMEM;
-               }
-               fw_priv->nr_pages++;
-       }
-       return 0;
+       err = fw_grow_paged_buf(fw_sysfs->fw_priv,
+                               PAGE_ALIGN(min_size) >> PAGE_SHIFT);
+       if (err)
+               fw_load_abort(fw_sysfs);
+       return err;
 }
 
 /**