Merge tag 'media/v5.8-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Jun 2020 20:09:38 +0000 (13:09 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Jun 2020 20:09:38 +0000 (13:09 -0700)
Pull more media updates from Mauro Carvalho Chehab:

 - a set of atomisp patches. They remove several abstraction layers, and
   fixes clang and gcc warnings (that were hidden via some macros that
   were disabling 4 or 5 types of warnings there). There are also some
   important fixes and sensor auto-detection on newer BIOSes via ACPI
   _DCM tables.

 - some fixes

* tag 'media/v5.8-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (95 commits)
  media: rkvdec: Fix H264 scaling list order
  media: v4l2-ctrls: Unset correct HEVC loop filter flag
  media: videobuf2-dma-contig: fix bad kfree in vb2_dma_contig_clear_max_seg_size
  media: v4l2-subdev.rst: correct information about v4l2 events
  media: s5p-mfc: Properly handle dma_parms for the allocated devices
  media: medium: cec: Make MEDIA_CEC_SUPPORT default to n if !MEDIA_SUPPORT
  media: cedrus: Implement runtime PM
  media: cedrus: Program output format during each run
  media: atomisp: improve ACPI/DMI detection logs
  media: Revert "media: atomisp: add Asus Transform T101HA ACPI vars"
  media: Revert "media: atomisp: Add some ACPI detection info"
  media: atomisp: improve sensor detection code to use _DSM table
  media: atomisp: get rid of an iomem abstraction layer
  media: atomisp: get rid of a string_support.h abstraction layer
  media: atomisp: use strscpy() instead of less secure variants
  media: atomisp: set DFS to MAX if sensor doesn't report fps
  media: atomisp: use different dfs failed messages
  media: atomisp: change the detection of ISP2401 at runtime
  media: atomisp: use macros from intel-family.h
  media: atomisp: don't set hpll_freq twice with different values
  ...

1  2 
drivers/staging/media/atomisp/pci/atomisp_v4l2.c
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c

@@@ -1,3 -1,4 +1,4 @@@
+ // SPDX-License-Identifier: GPL-2.0
  /*
   * Support for Medifield PNW Camera Imaging ISP subsystem.
   *
@@@ -42,7 -43,7 +43,7 @@@
  #include "hmm/hmm.h"
  #include "atomisp_trace_event.h"
  
- #include "hrt/hive_isp_css_mm_hrt.h"
+ #include "sh_css_firmware.h"
  
  #include "device_access.h"
  
@@@ -58,21 -59,21 +59,21 @@@ module_param(skip_fwload, uint, 0644)
  MODULE_PARM_DESC(skip_fwload, "Skip atomisp firmware load");
  
  /* set reserved memory pool size in page */
- static unsigned int repool_pgnr;
+ static unsigned int repool_pgnr = 32768;
  module_param(repool_pgnr, uint, 0644);
  MODULE_PARM_DESC(repool_pgnr,
-                "Set the reserved memory pool size in page (default:0)");
+                "Set the reserved memory pool size in page (default:32768)");
  
  /* set dynamic memory pool size in page */
  unsigned int dypool_pgnr = UINT_MAX;
  module_param(dypool_pgnr, uint, 0644);
  MODULE_PARM_DESC(dypool_pgnr,
-                "Set the dynamic memory pool size in page (default:0)");
+                "Set the dynamic memory pool size in page (default: unlimited)");
  
- bool dypool_enable;
+ bool dypool_enable = true;
  module_param(dypool_enable, bool, 0644);
  MODULE_PARM_DESC(dypool_enable,
-                "dynamic memory pool enable/disable (default:disable)");
+                "dynamic memory pool enable/disable (default:enabled)");
  
  /* memory optimization: deferred firmware loading */
  bool defer_fw_load;
@@@ -83,7 -84,7 +84,7 @@@ MODULE_PARM_DESC(defer_fw_load
  /* cross componnet debug message flag */
  int dbg_level;
  module_param(dbg_level, int, 0644);
- MODULE_PARM_DESC(dbg_level, "debug message on/off (default:off)");
+ MODULE_PARM_DESC(dbg_level, "debug message level (default:0)");
  
  /* log function switch */
  int dbg_func = 2;
@@@ -95,6 -96,10 +96,10 @@@ int mipicsi_flag
  module_param(mipicsi_flag, int, 0644);
  MODULE_PARM_DESC(mipicsi_flag, "mipi csi compression predictor algorithm");
  
+ static char firmware_name[256];
+ module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
+ MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the default firmware name.");
  /*set to 16x16 since this is the amount of lines and pixels the sensor
  exports extra. If these are kept at the 10x8 that they were on, in yuv
  downscaling modes incorrect resolutions where requested to the sensor
@@@ -119,11 -124,6 +124,6 @@@ MODULE_PARM_DESC(pad_h, "extra data fo
   * be to replace this to something stored inside atomisp allocated
   * structures.
   */
- bool atomisp_hw_is_isp2401;
- /* Types of atomisp hardware */
- #define HW_IS_ISP2400 0
- #define HW_IS_ISP2401 1
  
  struct device *atomisp_dev;
  
@@@ -349,52 -349,6 +349,6 @@@ static const struct atomisp_dfs_config 
        .dfs_table_size = ARRAY_SIZE(dfs_rules_byt),
  };
  
- static const struct atomisp_freq_scaling_rule dfs_rules_byt_cr[] = {
-       {
-               .width = ISP_FREQ_RULE_ANY,
-               .height = ISP_FREQ_RULE_ANY,
-               .fps = ISP_FREQ_RULE_ANY,
-               .isp_freq = ISP_FREQ_320MHZ,
-               .run_mode = ATOMISP_RUN_MODE_VIDEO,
-       },
-       {
-               .width = ISP_FREQ_RULE_ANY,
-               .height = ISP_FREQ_RULE_ANY,
-               .fps = ISP_FREQ_RULE_ANY,
-               .isp_freq = ISP_FREQ_320MHZ,
-               .run_mode = ATOMISP_RUN_MODE_STILL_CAPTURE,
-       },
-       {
-               .width = ISP_FREQ_RULE_ANY,
-               .height = ISP_FREQ_RULE_ANY,
-               .fps = ISP_FREQ_RULE_ANY,
-               .isp_freq = ISP_FREQ_320MHZ,
-               .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE,
-       },
-       {
-               .width = ISP_FREQ_RULE_ANY,
-               .height = ISP_FREQ_RULE_ANY,
-               .fps = ISP_FREQ_RULE_ANY,
-               .isp_freq = ISP_FREQ_320MHZ,
-               .run_mode = ATOMISP_RUN_MODE_PREVIEW,
-       },
-       {
-               .width = ISP_FREQ_RULE_ANY,
-               .height = ISP_FREQ_RULE_ANY,
-               .fps = ISP_FREQ_RULE_ANY,
-               .isp_freq = ISP_FREQ_320MHZ,
-               .run_mode = ATOMISP_RUN_MODE_SDV,
-       },
- };
- static const struct atomisp_dfs_config dfs_config_byt_cr = {
-       .lowest_freq = ISP_FREQ_200MHZ,
-       .max_freq_at_vmin = ISP_FREQ_320MHZ,
-       .highest_freq = ISP_FREQ_320MHZ,
-       .dfs_table = dfs_rules_byt_cr,
-       .dfs_table_size = ARRAY_SIZE(dfs_rules_byt_cr),
- };
  static const struct atomisp_freq_scaling_rule dfs_rules_cht[] = {
        {
                .width = ISP_FREQ_RULE_ANY,
@@@ -659,7 -613,7 +613,7 @@@ static int __maybe_unused atomisp_resto
         * which has bugs(like sighting:4567697 and 4567699) and
         * will be removed in B0
         */
-       atomisp_store_uint32(MRFLD_CSI_RECEIVER_SELECTION_REG, 1);
+       atomisp_css2_hw_store_32(MRFLD_CSI_RECEIVER_SELECTION_REG, 1);
        return 0;
  }
  
@@@ -689,7 -643,7 +643,7 @@@ static int atomisp_mrfld_pre_power_down
        if (!(irq & (1 << INTR_IIR)))
                goto done;
  
-       atomisp_store_uint32(MRFLD_INTR_CLEAR_REG, 0xFFFFFFFF);
+       atomisp_css2_hw_store_32(MRFLD_INTR_CLEAR_REG, 0xFFFFFFFF);
        atomisp_load_uint32(MRFLD_INTR_STATUS_REG, &irq);
        if (irq != 0) {
                dev_err(isp->dev,
  
                pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq);
                if (!(irq & (1 << INTR_IIR))) {
-                       atomisp_store_uint32(MRFLD_INTR_ENABLE_REG, 0x0);
+                       atomisp_css2_hw_store_32(MRFLD_INTR_ENABLE_REG, 0x0);
                        goto done;
                }
                dev_err(isp->dev,
@@@ -824,15 -778,17 +778,15 @@@ static int atomisp_mrfld_power(struct a
  /* Workaround for pmu_nc_set_power_state not ready in MRFLD */
  int atomisp_mrfld_power_down(struct atomisp_device *isp)
  {
 -      return 0;
 -// FIXME: at least with ISP2401, the code below causes the driver to break
 -//    return atomisp_mrfld_power(isp, false);
 +// FIXME: at least with ISP2401, enabling this code causes the driver to break
 +      return 0 && atomisp_mrfld_power(isp, false);
  }
  
  /* Workaround for pmu_nc_set_power_state not ready in MRFLD */
  int atomisp_mrfld_power_up(struct atomisp_device *isp)
  {
 -      return 0;
 -// FIXME: at least with ISP2401, the code below causes the driver to break
 -//    return atomisp_mrfld_power(isp, true);
 +// FIXME: at least with ISP2401, enabling this code causes the driver to break
 +      return 0 && atomisp_mrfld_power(isp, true);
  }
  
  int atomisp_runtime_suspend(struct device *dev)
@@@ -1084,15 -1040,15 +1038,15 @@@ static int atomisp_subdev_probe(struct 
        /* FIXME: should return -EPROBE_DEFER if not all subdevs were probed */
        for (count = 0; count < SUBDEV_WAIT_TIMEOUT_MAX_COUNT; count++) {
                int camera_count = 0;
                for (subdevs = pdata->subdevs; subdevs->type; ++subdevs) {
                        if (subdevs->type == RAW_CAMERA ||
                            subdevs->type == SOC_CAMERA)
-                               camera_count ++;
+                               camera_count++;
                }
                if (camera_count)
                        break;
                msleep(SUBDEV_WAIT_TIMEOUT);
-               count++;
        }
        /* Wait more time to give more time for subdev init code to finish */
        msleep(5 * SUBDEV_WAIT_TIMEOUT);
  
                switch (subdevs->type) {
                case RAW_CAMERA:
-                       raw_index = isp->input_cnt;
                        dev_dbg(isp->dev, "raw_index: %d\n", raw_index);
-                       /* pass-though */
+                       raw_index = isp->input_cnt;
+                       /* fall through */
                case SOC_CAMERA:
                        dev_dbg(isp->dev, "SOC_INDEX: %d\n", isp->input_cnt);
                        if (isp->input_cnt >= ATOM_ISP_MAX_INPUTS) {
@@@ -1250,7 -1206,7 +1204,7 @@@ static int atomisp_register_entities(st
  
        isp->media_dev.dev = isp->dev;
  
-       strlcpy(isp->media_dev.model, "Intel Atom ISP",
+       strscpy(isp->media_dev.model, "Intel Atom ISP",
                sizeof(isp->media_dev.model));
  
        media_device_init(&isp->media_dev);
@@@ -1447,19 -1403,23 +1401,23 @@@ atomisp_load_firmware(struct atomisp_de
        if (skip_fwload)
                return NULL;
  
-       if ((isp->media_dev.hw_revision  >> ATOMISP_HW_REVISION_SHIFT)
-            == ATOMISP_HW_REVISION_ISP2401)
-               fw_path = "shisp_2401a0_v21.bin";
-       if (isp->media_dev.hw_revision ==
-           ((ATOMISP_HW_REVISION_ISP2401_LEGACY << ATOMISP_HW_REVISION_SHIFT)
-            | ATOMISP_HW_STEPPING_A0))
-               fw_path = "shisp_2401a0_legacy_v21.bin";
-       if (isp->media_dev.hw_revision ==
-           ((ATOMISP_HW_REVISION_ISP2400 << ATOMISP_HW_REVISION_SHIFT)
-            | ATOMISP_HW_STEPPING_B0))
-               fw_path = "shisp_2400b0_v21.bin";
+       if (firmware_name[0] != '\0') {
+               fw_path = firmware_name;
+       } else {
+               if ((isp->media_dev.hw_revision  >> ATOMISP_HW_REVISION_SHIFT)
+                   == ATOMISP_HW_REVISION_ISP2401)
+                       fw_path = "shisp_2401a0_v21.bin";
+               if (isp->media_dev.hw_revision ==
+                   ((ATOMISP_HW_REVISION_ISP2401_LEGACY << ATOMISP_HW_REVISION_SHIFT)
+                   | ATOMISP_HW_STEPPING_A0))
+                       fw_path = "shisp_2401a0_legacy_v21.bin";
+               if (isp->media_dev.hw_revision ==
+                   ((ATOMISP_HW_REVISION_ISP2400 << ATOMISP_HW_REVISION_SHIFT)
+                   | ATOMISP_HW_STEPPING_B0))
+                       fw_path = "shisp_2400b0_v21.bin";
+       }
  
        if (!fw_path) {
                dev_err(isp->dev, "Unsupported hw_revision 0x%x\n",
@@@ -1494,21 -1454,17 +1452,17 @@@ static bool is_valid_device(struct pci_
        switch (id->device & ATOMISP_PCI_DEVICE_SOC_MASK) {
        case ATOMISP_PCI_DEVICE_SOC_MRFLD:
                a0_max_id = ATOMISP_PCI_REV_MRFLD_A0_MAX;
-               atomisp_hw_is_isp2401 = false;
                name = "Merrifield";
                break;
        case ATOMISP_PCI_DEVICE_SOC_BYT:
                a0_max_id = ATOMISP_PCI_REV_BYT_A0_MAX;
-               atomisp_hw_is_isp2401 = false;
                name = "Baytrail";
                break;
        case ATOMISP_PCI_DEVICE_SOC_ANN:
                name = "Anniedale";
-               atomisp_hw_is_isp2401 = true;
                break;
        case ATOMISP_PCI_DEVICE_SOC_CHT:
                name = "Cherrytrail";
-               atomisp_hw_is_isp2401 = true;
                break;
        default:
                dev_err(&dev->dev, "%s: unknown device ID %x04:%x04\n",
         */
  
  #if defined(ISP2400)
-       if (atomisp_hw_is_isp2401) {
+       if (IS_ISP2401) {
                dev_err(&dev->dev, "Support for %s (ISP2401) was disabled at compile time\n",
                        name);
                return false;
        }
  #else
-       if (!atomisp_hw_is_isp2401) {
+       if (!IS_ISP2401) {
                dev_err(&dev->dev, "Support for %s (ISP2400) was disabled at compile time\n",
                        name);
                return false;
  
        dev_info(&dev->dev, "Detected %s version %d (ISP240%c) on %s\n",
                name, dev->revision,
-               atomisp_hw_is_isp2401 ? '1' : '0',
+               IS_ISP2401 ? '1' : '0',
                product);
  
        return true;
@@@ -1564,7 -1520,8 +1518,8 @@@ static int init_atomisp_wdts(struct ato
  
        for (i = 0; i < isp->num_of_streams; i++) {
                struct atomisp_sub_device *asd = &isp->asd[i];
-               if (!atomisp_hw_is_isp2401)
+               if (!IS_ISP2401)
                        timer_setup(&asd->wdt, atomisp_wdt, 0);
                else {
                        timer_setup(&asd->video_out_capture.wdt,
@@@ -1670,20 -1627,29 +1625,29 @@@ static int atomisp_pci_probe(struct pci
                    (ATOMISP_HW_REVISION_ISP2400
                     << ATOMISP_HW_REVISION_SHIFT) |
                    ATOMISP_HW_STEPPING_B0;
- #ifdef FIXME
-               if (INTEL_MID_BOARD(3, TABLET, BYT, BLK, PRO, CRV2) ||
-                   INTEL_MID_BOARD(3, TABLET, BYT, BLK, ENG, CRV2)) {
-                       isp->dfs = &dfs_config_byt_cr;
-                       isp->hpll_freq = HPLL_FREQ_2000MHZ;
-               } else
- #endif
-               {
-                       isp->dfs = &dfs_config_byt;
-                       isp->hpll_freq = HPLL_FREQ_1600MHZ;
-               }
-               /* HPLL frequency is known to be device-specific, but we don't
+               /*
+                * Note: some Intel-based tablets with Android use a different
+                * DFS table. Based on the comments at the Yocto Aero meta
+                * version of this driver (at the ssid.h header), they're
+                * identified via a "spid" var:
+                *
+                *      androidboot.spid=vend:cust:manu:plat:prod:hard
+                *
+                * As we don't have this upstream, nor we know enough details
+                * to use a DMI or PCI match table, the old code was just
+                * removed, but let's keep a note here as a reminder that,
+                * for certain devices, we may need to limit the max DFS
+                * frequency to be below certain values, adjusting the
+                * resolution accordingly.
+                */
+               isp->dfs = &dfs_config_byt;
+               /*
+                * HPLL frequency is known to be device-specific, but we don't
                 * have specs yet for exactly how it varies.  Default to
-                * BYT-CR but let provisioning set it via EFI variable */
+                * BYT-CR but let provisioning set it via EFI variable
+                */
                isp->hpll_freq = gmin_get_var_int(&dev->dev, false, "HpllFreq",
                                                  HPLL_FREQ_2000MHZ);
  
                default:
                        isp->hpll_freq = HPLL_FREQ_1600MHZ;
                        dev_warn(isp->dev,
-                                "read HPLL from cck failed.default 1600MHz.\n");
+                                "read HPLL from cck failed. Default to 1600 MHz.\n");
                }
                break;
        default:
                        goto load_fw_fail;
                }
  
-               err = atomisp_css_check_firmware_version(isp);
+               err = sh_css_check_firmware_version(isp->dev,
+                                                   isp->firmware->data);
                if (err) {
                        dev_dbg(&dev->dev, "Firmware version check failed\n");
                        goto fw_validation_fail;
         * bugs(like sighting:4567697 and 4567699) and will be removed
         * in B0
         */
-       atomisp_store_uint32(MRFLD_CSI_RECEIVER_SELECTION_REG, 1);
+       atomisp_css2_hw_store_32(MRFLD_CSI_RECEIVER_SELECTION_REG, 1);
  
        if ((id->device & ATOMISP_PCI_DEVICE_SOC_MASK) ==
            ATOMISP_PCI_DEVICE_SOC_MRFLD) {
@@@ -1938,7 -1905,7 +1903,7 @@@ static void atomisp_pci_remove(struct p
  
        atomisp_acc_cleanup(isp);
  
-       atomisp_css_unload_firmware(isp);
+       ia_css_unload_firmware();
        hmm_cleanup();
  
        pm_runtime_forbid(&dev->dev);
@@@ -1,3 -1,4 +1,4 @@@
+ // SPDX-License-Identifier: GPL-2.0
  /*
   * Support for Medifield PNW Camera Imaging ISP subsystem.
   *
@@@ -659,6 -660,8 +660,8 @@@ static void free_private_bo_pages(struc
                                break;
                        }
  
+                       /* fall through */
                /*
                 * if dynamic memory pool doesn't exist, need to free
                 * pages to system directly.
@@@ -854,109 -857,20 +857,20 @@@ static void free_private_pages(struct h
        kfree(bo->page_obj);
  }
  
- /*
-  * Hacked from kernel function __get_user_pages in mm/memory.c
-  *
-  * Handle buffers allocated by other kernel space driver and mmaped into user
-  * space, function Ignore the VM_PFNMAP and VM_IO flag in VMA structure
-  *
-  * Get physical pages from user space virtual address and update into page list
-  */
- static int __get_pfnmap_pages(struct task_struct *tsk, struct mm_struct *mm,
-                             unsigned long start, int nr_pages,
-                             unsigned int gup_flags, struct page **pages,
-                             struct vm_area_struct **vmas)
- {
-       int i, ret;
-       unsigned long vm_flags;
-       if (nr_pages <= 0)
-               return 0;
-       VM_BUG_ON(!!pages != !!(gup_flags & FOLL_GET));
-       /*
-        * Require read or write permissions.
-        * If FOLL_FORCE is set, we only require the "MAY" flags.
-        */
-       vm_flags  = (gup_flags & FOLL_WRITE) ?
-                   (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
-       vm_flags &= (gup_flags & FOLL_FORCE) ?
-                   (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
-       i = 0;
-       do {
-               struct vm_area_struct *vma;
-               vma = find_vma(mm, start);
-               if (!vma) {
-                       dev_err(atomisp_dev, "find_vma failed\n");
-                       return i ? : -EFAULT;
-               }
-               if (is_vm_hugetlb_page(vma)) {
-                       /*
-                       i = follow_hugetlb_page(mm, vma, pages, vmas,
-                                       &start, &nr_pages, i, gup_flags);
-                       */
-                       continue;
-               }
-               do {
-                       struct page *page;
-                       unsigned long pfn;
-                       /*
-                        * If we have a pending SIGKILL, don't keep faulting
-                        * pages and potentially allocating memory.
-                        */
-                       if (unlikely(fatal_signal_pending(current))) {
-                               dev_err(atomisp_dev,
-                                       "fatal_signal_pending in %s\n",
-                                       __func__);
-                               return i ? i : -ERESTARTSYS;
-                       }
-                       ret = follow_pfn(vma, start, &pfn);
-                       if (ret) {
-                               dev_err(atomisp_dev, "follow_pfn() failed\n");
-                               return i ? : -EFAULT;
-                       }
-                       page = pfn_to_page(pfn);
-                       if (IS_ERR(page))
-                               return i ? i : PTR_ERR(page);
-                       if (pages) {
-                               pages[i] = page;
-                               get_page(page);
-                               flush_anon_page(vma, page, start);
-                               flush_dcache_page(page);
-                       }
-                       if (vmas)
-                               vmas[i] = vma;
-                       i++;
-                       start += PAGE_SIZE;
-                       nr_pages--;
-               } while (nr_pages && start < vma->vm_end);
-       } while (nr_pages);
-       return i;
- }
- static int get_pfnmap_pages(struct task_struct *tsk, struct mm_struct *mm,
-                           unsigned long start, int nr_pages, int write, int force,
-                           struct page **pages, struct vm_area_struct **vmas)
+ static void free_user_pages(struct hmm_buffer_object *bo)
  {
-       int flags = FOLL_TOUCH;
+       int i;
  
-       if (pages)
-               flags |= FOLL_GET;
-       if (write)
-               flags |= FOLL_WRITE;
-       if (force)
-               flags |= FOLL_FORCE;
+       hmm_mem_stat.usr_size -= bo->pgnr;
  
-       return __get_pfnmap_pages(tsk, mm, start, nr_pages, flags, pages, vmas);
+       if (bo->mem_type == HMM_BO_MEM_TYPE_PFN) {
+               unpin_user_pages(bo->pages, bo->pgnr);
+       } else {
+               for (i = 0; i < bo->pgnr; i++)
+                       put_page(bo->pages[i]);
+       }
+       kfree(bo->pages);
+       kfree(bo->page_obj);
  }
  
  /*
@@@ -982,9 -896,9 +896,9 @@@ static int alloc_user_pages(struct hmm_
        }
  
        mutex_unlock(&bo->mutex);
 -      down_read(&current->mm->mmap_sem);
 +      mmap_read_lock(current->mm);
        vma = find_vma(current->mm, (unsigned long)userptr);
 -      up_read(&current->mm->mmap_sem);
 +      mmap_read_unlock(current->mm);
        if (!vma) {
                dev_err(atomisp_dev, "find_vma failed\n");
                kfree(bo->page_obj);
         * Handle frame buffer allocated in other kerenl space driver
         * and map to user space
         */
+       userptr = untagged_addr(userptr);
+       bo->pages = pages;
        if (vma->vm_flags & (VM_IO | VM_PFNMAP)) {
-               page_nr = get_pfnmap_pages(current, current->mm,
-                                          (unsigned long)userptr,
-                                          (int)(bo->pgnr), 1, 0,
-                                          pages, NULL);
+               page_nr = pin_user_pages((unsigned long)userptr, bo->pgnr,
+                                        FOLL_LONGTERM | FOLL_WRITE,
+                                        pages, NULL);
                bo->mem_type = HMM_BO_MEM_TYPE_PFN;
        } else {
                /*Handle frame buffer allocated in user space*/
                bo->mem_type = HMM_BO_MEM_TYPE_USER;
        }
  
+       dev_dbg(atomisp_dev, "%s: %d %s pages were allocated as 0x%08x\n",
+               __func__,
+               bo->pgnr,
+               bo->mem_type == HMM_BO_MEM_TYPE_USER ? "user" : "pfn", page_nr);
+       hmm_mem_stat.usr_size += bo->pgnr;
        /* can be written by caller, not forced */
        if (page_nr != bo->pgnr) {
                dev_err(atomisp_dev,
                bo->page_obj[i].page = pages[i];
                bo->page_obj[i].type = HMM_PAGE_TYPE_GENERAL;
        }
-       hmm_mem_stat.usr_size += bo->pgnr;
-       kfree(pages);
  
        return 0;
  
  out_of_mem:
-       for (i = 0; i < page_nr; i++)
-               put_page(pages[i]);
-       kfree(pages);
-       kfree(bo->page_obj);
-       return -ENOMEM;
- }
  
- static void free_user_pages(struct hmm_buffer_object *bo)
- {
-       int i;
+       free_user_pages(bo);
  
-       for (i = 0; i < bo->pgnr; i++)
-               put_page(bo->page_obj[i].page);
-       hmm_mem_stat.usr_size -= bo->pgnr;
-       kfree(bo->page_obj);
+       return -ENOMEM;
  }
  
  /*