Merge tag 'char-misc-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregk...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Sep 2021 15:35:06 +0000 (08:35 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Sep 2021 15:35:06 +0000 (08:35 -0700)
Pull char / misc driver updates from Greg KH:
 "Here is the big set of char/misc driver changes for 5.15-rc1.

  Lots of different driver subsystems are being updated in here,
  notably:

   - mhi subsystem update

   - fpga subsystem update

   - coresight/hwtracing subsystem update

   - interconnect subsystem update

   - nvmem subsystem update

   - parport drivers update

   - phy subsystem update

   - soundwire subsystem update

  and there are some other char/misc drivers being updated as well:

   - binder driver additions

   - new misc drivers

   - lkdtm driver updates

   - mei driver updates

   - sram driver updates

   - other minor driver updates.

  Note, there are no habanalabs driver updates in this pull request,
  that will probably come later before -rc1 is out in a different
  request.

  All of these have been in linux-next for a while with no reported
  problems"

* tag 'char-misc-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (169 commits)
  Revert "bus: mhi: Add inbound buffers allocation flag"
  misc/pvpanic: fix set driver data
  VMCI: fix NULL pointer dereference when unmapping queue pair
  char: mware: fix returnvar.cocci warnings
  parport: remove non-zero check on count
  soundwire: cadence: do not extend reset delay
  soundwire: intel: conditionally exit clock stop mode on system suspend
  soundwire: intel: skip suspend/resume/wake when link was not started
  soundwire: intel: fix potential race condition during power down
  phy: qcom-qmp: Add support for SM6115 UFS phy
  dt-bindings: phy: qcom,qmp: Add SM6115 UFS PHY bindings
  phy: qmp: Provide unique clock names for DP clocks
  lkdtm: remove IDE_CORE_CP crashpoint
  lkdtm: replace SCSI_DISPATCH_CMD with SCSI_QUEUE_RQ
  coresight: Replace deprecated CPU-hotplug functions.
  Documentation: coresight: Add documentation for CoreSight config
  coresight: syscfg: Add initial configfs support
  coresight: config: Add preloaded configurations
  coresight: etm4x: Add complex configuration handlers to etmv4
  coresight: etm-perf: Update to activate selected configuration
  ...

1  2 
drivers/bus/fsl-mc/fsl-mc-bus.c
drivers/bus/mhi/pci_generic.c
include/linux/mhi.h

@@@ -63,11 -63,14 +63,14 @@@ struct fsl_mc_addr_translation_range 
  
  #define FSL_MC_GCR1   0x0
  #define GCR1_P1_STOP  BIT(31)
+ #define GCR1_P2_STOP  BIT(30)
  
  #define FSL_MC_FAPR   0x28
  #define MC_FAPR_PL    BIT(18)
  #define MC_FAPR_BMT   BIT(17)
  
+ static phys_addr_t mc_portal_base_phys_addr;
  /**
   * fsl_mc_bus_match - device to driver matching callback
   * @dev: the fsl-mc device to match against
@@@ -220,7 -223,7 +223,7 @@@ static int scan_fsl_mc_bus(struct devic
        root_mc_dev = to_fsl_mc_device(dev);
        root_mc_bus = to_fsl_mc_bus(root_mc_dev);
        mutex_lock(&root_mc_bus->scan_mutex);
-       dprc_scan_objects(root_mc_dev, NULL);
+       dprc_scan_objects(root_mc_dev, false);
        mutex_unlock(&root_mc_bus->scan_mutex);
  
  exit:
@@@ -703,14 -706,30 +706,30 @@@ static int fsl_mc_device_get_mmio_regio
                 * If base address is in the region_desc use it otherwise
                 * revert to old mechanism
                 */
-               if (region_desc.base_address)
+               if (region_desc.base_address) {
                        regions[i].start = region_desc.base_address +
                                                region_desc.base_offset;
-               else
+               } else {
                        error = translate_mc_addr(mc_dev, mc_region_type,
                                          region_desc.base_offset,
                                          &regions[i].start);
  
+                       /*
+                        * Some versions of the MC firmware wrongly report
+                        * 0 for register base address of the DPMCP associated
+                        * with child DPRC objects thus rendering them unusable.
+                        * This is particularly troublesome in ACPI boot
+                        * scenarios where the legacy way of extracting this
+                        * base address from the device tree does not apply.
+                        * Given that DPMCPs share the same base address,
+                        * workaround this by using the base address extracted
+                        * from the root DPRC container.
+                        */
+                       if (is_fsl_mc_bus_dprc(mc_dev) &&
+                           regions[i].start == region_desc.base_offset)
+                               regions[i].start += mc_portal_base_phys_addr;
+               }
                if (error < 0) {
                        dev_err(parent_dev,
                                "Invalid MC offset: %#x (for %s.%d\'s region %d)\n",
@@@ -895,6 -914,8 +914,8 @@@ error_cleanup_dev
  }
  EXPORT_SYMBOL_GPL(fsl_mc_device_add);
  
+ static struct notifier_block fsl_mc_nb;
  /**
   * fsl_mc_device_remove - Remove an fsl-mc device from being visible to
   * Linux
@@@ -914,8 -935,7 +935,8 @@@ void fsl_mc_device_remove(struct fsl_mc
  }
  EXPORT_SYMBOL_GPL(fsl_mc_device_remove);
  
 -struct fsl_mc_device *fsl_mc_get_endpoint(struct fsl_mc_device *mc_dev)
 +struct fsl_mc_device *fsl_mc_get_endpoint(struct fsl_mc_device *mc_dev,
 +                                        u16 if_id)
  {
        struct fsl_mc_device *mc_bus_dev, *endpoint;
        struct fsl_mc_obj_desc endpoint_desc = {{ 0 }};
        mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
        strcpy(endpoint1.type, mc_dev->obj_desc.type);
        endpoint1.id = mc_dev->obj_desc.id;
 +      endpoint1.if_id = if_id;
  
        err = dprc_get_connection(mc_bus_dev->mc_io, 0,
                                  mc_bus_dev->mc_handle,
         * We know that the device has an endpoint because we verified by
         * interrogating the firmware. This is the case when the device was not
         * yet discovered by the fsl-mc bus, thus the lookup returned NULL.
-        * Differentiate this case by returning EPROBE_DEFER.
+        * Force a rescan of the devices in this container and retry the lookup.
+        */
+       if (!endpoint) {
+               struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
+               if (mutex_trylock(&mc_bus->scan_mutex)) {
+                       err = dprc_scan_objects(mc_bus_dev, true);
+                       mutex_unlock(&mc_bus->scan_mutex);
+               }
+               if (err < 0)
+                       return ERR_PTR(err);
+       }
+       endpoint = fsl_mc_device_lookup(&endpoint_desc, mc_bus_dev);
+       /*
+        * This means that the endpoint might reside in a different isolation
+        * context (DPRC/container). Not much to do, so return a permssion
+        * error.
         */
        if (!endpoint)
-               return ERR_PTR(-EPROBE_DEFER);
+               return ERR_PTR(-EPERM);
  
        return endpoint;
  }
@@@ -1091,17 -1128,6 +1130,6 @@@ static int fsl_mc_bus_probe(struct plat
        }
  
        if (mc->fsl_mc_regs) {
-               /*
-                * Some bootloaders pause the MC firmware before booting the
-                * kernel so that MC will not cause faults as soon as the
-                * SMMU probes due to the fact that there's no configuration
-                * in place for MC.
-                * At this point MC should have all its SMMU setup done so make
-                * sure it is resumed.
-                */
-               writel(readl(mc->fsl_mc_regs + FSL_MC_GCR1) & (~GCR1_P1_STOP),
-                      mc->fsl_mc_regs + FSL_MC_GCR1);
                if (IS_ENABLED(CONFIG_ACPI) && !dev_of_node(&pdev->dev)) {
                        mc_stream_id = readl(mc->fsl_mc_regs + FSL_MC_FAPR);
                        /*
                        error = acpi_dma_configure_id(&pdev->dev,
                                                      DEV_DMA_COHERENT,
                                                      &mc_stream_id);
+                       if (error == -EPROBE_DEFER)
+                               return error;
                        if (error)
                                dev_warn(&pdev->dev,
                                         "failed to configure dma: %d.\n",
                                         error);
                }
+               /*
+                * Some bootloaders pause the MC firmware before booting the
+                * kernel so that MC will not cause faults as soon as the
+                * SMMU probes due to the fact that there's no configuration
+                * in place for MC.
+                * At this point MC should have all its SMMU setup done so make
+                * sure it is resumed.
+                */
+               writel(readl(mc->fsl_mc_regs + FSL_MC_GCR1) &
+                            (~(GCR1_P1_STOP | GCR1_P2_STOP)),
+                      mc->fsl_mc_regs + FSL_MC_GCR1);
        }
  
        /*
        plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        mc_portal_phys_addr = plat_res->start;
        mc_portal_size = resource_size(plat_res);
+       mc_portal_base_phys_addr = mc_portal_phys_addr & ~0x3ffffff;
        error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
                                 mc_portal_size, NULL,
                                 FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io);
@@@ -1201,9 -1243,26 +1245,26 @@@ static int fsl_mc_bus_remove(struct pla
        fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);
        mc->root_mc_bus_dev->mc_io = NULL;
  
+       bus_unregister_notifier(&fsl_mc_bus_type, &fsl_mc_nb);
+       if (mc->fsl_mc_regs) {
+               /*
+                * Pause the MC firmware so that it doesn't crash in certain
+                * scenarios, such as kexec.
+                */
+               writel(readl(mc->fsl_mc_regs + FSL_MC_GCR1) |
+                      (GCR1_P1_STOP | GCR1_P2_STOP),
+                      mc->fsl_mc_regs + FSL_MC_GCR1);
+       }
        return 0;
  }
  
+ static void fsl_mc_bus_shutdown(struct platform_device *pdev)
+ {
+       fsl_mc_bus_remove(pdev);
+ }
  static const struct of_device_id fsl_mc_bus_match_table[] = {
        {.compatible = "fsl,qoriq-mc",},
        {},
@@@ -1226,6 -1285,45 +1287,45 @@@ static struct platform_driver fsl_mc_bu
                   },
        .probe = fsl_mc_bus_probe,
        .remove = fsl_mc_bus_remove,
+       .shutdown = fsl_mc_bus_shutdown,
+ };
+ static int fsl_mc_bus_notifier(struct notifier_block *nb,
+                              unsigned long action, void *data)
+ {
+       struct device *dev = data;
+       struct resource *res;
+       void __iomem *fsl_mc_regs;
+       if (action != BUS_NOTIFY_ADD_DEVICE)
+               return 0;
+       if (!of_match_device(fsl_mc_bus_match_table, dev) &&
+           !acpi_match_device(fsl_mc_bus_acpi_match_table, dev))
+               return 0;
+       res = platform_get_resource(to_platform_device(dev), IORESOURCE_MEM, 1);
+       if (!res)
+               return 0;
+       fsl_mc_regs = ioremap(res->start, resource_size(res));
+       if (!fsl_mc_regs)
+               return 0;
+       /*
+        * Make sure that the MC firmware is paused before the IOMMU setup for
+        * it is done or otherwise the firmware will crash right after the SMMU
+        * gets probed and enabled.
+        */
+       writel(readl(fsl_mc_regs + FSL_MC_GCR1) | (GCR1_P1_STOP | GCR1_P2_STOP),
+              fsl_mc_regs + FSL_MC_GCR1);
+       iounmap(fsl_mc_regs);
+       return 0;
+ }
+ static struct notifier_block fsl_mc_nb = {
+       .notifier_call = fsl_mc_bus_notifier,
  };
  
  static int __init fsl_mc_bus_driver_init(void)
        if (error < 0)
                goto error_cleanup_dprc_driver;
  
-       return 0;
+       return bus_register_notifier(&platform_bus_type, &fsl_mc_nb);
  
  error_cleanup_dprc_driver:
        dprc_driver_exit();
@@@ -32,7 -32,6 +32,7 @@@
   * @edl: emergency download mode firmware path (if any)
   * @bar_num: PCI base address register to use for MHI MMIO register space
   * @dma_data_width: DMA transfer word size (32 or 64 bits)
 + * @mru_default: default MRU size for MBIM network packets
   * @sideband_wake: Devices using dedicated sideband GPIO for wakeup instead
   *               of inband wake support (such as sdx24)
   */
@@@ -43,7 -42,6 +43,7 @@@ struct mhi_pci_dev_info 
        const char *edl;
        unsigned int bar_num;
        unsigned int dma_data_width;
 +      unsigned int mru_default;
        bool sideband_wake;
  };
  
@@@ -274,7 -272,6 +274,7 @@@ static const struct mhi_pci_dev_info mh
        .config = &modem_qcom_v1_mhiv_config,
        .bar_num = MHI_PCI_DEFAULT_BAR_NUM,
        .dma_data_width = 32,
 +      .mru_default = 32768,
        .sideband_wake = false,
  };
  
@@@ -369,6 -366,40 +369,40 @@@ static const struct mhi_pci_dev_info mh
        .sideband_wake = false,
  };
  
+ static const struct mhi_channel_config mhi_mv31_channels[] = {
+       MHI_CHANNEL_CONFIG_UL(0, "LOOPBACK", 64, 0),
+       MHI_CHANNEL_CONFIG_DL(1, "LOOPBACK", 64, 0),
+       /* MBIM Control Channel */
+       MHI_CHANNEL_CONFIG_UL(12, "MBIM", 64, 0),
+       MHI_CHANNEL_CONFIG_DL(13, "MBIM", 64, 0),
+       /* MBIM Data Channel */
+       MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0_MBIM", 512, 2),
+       MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0_MBIM", 512, 3),
+ };
+ static struct mhi_event_config mhi_mv31_events[] = {
+       MHI_EVENT_CONFIG_CTRL(0, 256),
+       MHI_EVENT_CONFIG_DATA(1, 256),
+       MHI_EVENT_CONFIG_HW_DATA(2, 1024, 100),
+       MHI_EVENT_CONFIG_HW_DATA(3, 1024, 101),
+ };
+ static const struct mhi_controller_config modem_mv31_config = {
+       .max_channels = 128,
+       .timeout_ms = 20000,
+       .num_channels = ARRAY_SIZE(mhi_mv31_channels),
+       .ch_cfg = mhi_mv31_channels,
+       .num_events = ARRAY_SIZE(mhi_mv31_events),
+       .event_cfg = mhi_mv31_events,
+ };
+ static const struct mhi_pci_dev_info mhi_mv31_info = {
+       .name = "cinterion-mv31",
+       .config = &modem_mv31_config,
+       .bar_num = MHI_PCI_DEFAULT_BAR_NUM,
+       .dma_data_width = 32,
+ };
  static const struct pci_device_id mhi_pci_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0306),
                .driver_data = (kernel_ulong_t) &mhi_qcom_sdx55_info },
        /* DW5930e (sdx55), Non-eSIM, It's also T99W175 */
        { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0b1),
                .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx55_info },
+       /* MV31-W (Cinterion) */
+       { PCI_DEVICE(0x1269, 0x00b3),
+               .driver_data = (kernel_ulong_t) &mhi_mv31_info },
        {  }
  };
  MODULE_DEVICE_TABLE(pci, mhi_pci_id_table);
@@@ -490,6 -524,7 +527,7 @@@ static int mhi_pci_claim(struct mhi_con
                return err;
        }
        mhi_cntrl->regs = pcim_iomap_table(pdev)[bar_num];
+       mhi_cntrl->reg_len = pci_resource_len(pdev, bar_num);
  
        err = pci_set_dma_mask(pdev, dma_mask);
        if (err) {
@@@ -667,7 -702,6 +705,7 @@@ static int mhi_pci_probe(struct pci_de
        mhi_cntrl->status_cb = mhi_pci_status_cb;
        mhi_cntrl->runtime_get = mhi_pci_runtime_get;
        mhi_cntrl->runtime_put = mhi_pci_runtime_put;
 +      mhi_cntrl->mru = info->mru_default;
  
        if (info->sideband_wake) {
                mhi_cntrl->wake_get = mhi_pci_wake_get_nop;
diff --combined include/linux/mhi.h
@@@ -303,6 -303,7 +303,7 @@@ struct mhi_controller_config 
   * @rddm_size: RAM dump size that host should allocate for debugging purpose
   * @sbl_size: SBL image size downloaded through BHIe (optional)
   * @seg_len: BHIe vector size (optional)
+  * @reg_len: Length of the MHI MMIO region (required)
   * @fbc_image: Points to firmware image buffer
   * @rddm_image: Points to RAM dump buffer
   * @mhi_chan: Points to the channel configuration table
   * @fbc_download: MHI host needs to do complete image transfer (optional)
   * @wake_set: Device wakeup set flag
   * @irq_flags: irq flags passed to request_irq (optional)
 + * @mru: the default MRU for the MHI device
   *
   * Fields marked as (required) need to be populated by the controller driver
   * before calling mhi_register_controller(). For the fields marked as (optional)
@@@ -387,6 -387,7 +388,7 @@@ struct mhi_controller 
        size_t rddm_size;
        size_t sbl_size;
        size_t seg_len;
+       size_t reg_len;
        struct image_info *fbc_image;
        struct image_info *rddm_image;
        struct mhi_chan *mhi_chan;
        bool fbc_download;
        bool wake_set;
        unsigned long irq_flags;
 +      u32 mru;
  };
  
  /**