Merge tag 'mhi-for-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 11 Aug 2023 19:26:23 +0000 (21:26 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 11 Aug 2023 19:26:23 +0000 (21:26 +0200)
Manivannan writes:

MHI Host
========

Core
----

- Skipped MHI reset if the device is in RDDM EE (Ramdump mode) since the device
  cannot process reset request.

- Updated the sysfs contact details to use MHI list instead of bouncing
  codeaurora email ids.

- Added support to allow MHI client drivers to provide the device firmware via
  a pointer. This is required to support new firmware format to be used by
  ath11k drivers.

- Used vcalloc instead of vzalloc to protect against multiplication overflows.

- Removed decrementing one unused parameter.

pci_generic
-----------

- Added support for MHI SW channels (IP_SW0) so that the host can transfer data
  from devices over networking interface through this specific channel.

- Added support for a clone of Quectel RM520N-GL modem which uses a different
  PID as it is targeted for laptop usecase.

- Added support for a clone of Quectel EM160R-GL modem which uses a different
  PID as it is targeted for laptop usecase.

- Added support for another clone of Quectel RM520N-GL modem which uses a
  different PID as it is targeted for Lenovo laptop usecase.

- Added support for Dell DW5932e modem (both eSIM and non-eSIM variants).

- Added support for Telit FE990 modem.

* tag 'mhi-for-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi:
  bus: mhi: host: pci_generic: add support for Telit FE990 modem
  bus: mhi: host: remove unused-but-set parameter
  bus: mhi: host: pci_generic: Add support for Quectel RM520N-GL Lenovo variant
  bus: mhi: host: allow MHI client drivers to provide the firmware via a pointer
  docs: ABI: sysfs-bus-mhi: Update contact info
  bus: mhi: host: use vmalloc_array and vcalloc
  bus: mhi: host: pci_generic: Add support for Dell DW5932e
  bus: mhi: host: pci_generic: Add support for Quectel RM520N-GL modem
  bus: mhi: host: pci_generic: Add support for Quectel EM160R-GL modem
  bus: mhi: host: pci_generic: Add support for IP_SW0 channels
  bus: mhi: host: Skip MHI reset if device is in RDDM

Documentation/ABI/stable/sysfs-bus-mhi
drivers/bus/mhi/host/boot.c
drivers/bus/mhi/host/init.c
drivers/bus/mhi/host/main.c
drivers/bus/mhi/host/pci_generic.c
drivers/bus/mhi/host/pm.c
include/linux/mhi.h

index 96ccc33..1a47f9e 100644 (file)
@@ -1,7 +1,7 @@
 What:          /sys/bus/mhi/devices/.../serialnumber
 Date:          Sept 2020
 KernelVersion: 5.10
-Contact:       Bhaumik Bhatt <bbhatt@codeaurora.org>
+Contact:       mhi@lists.linux.dev
 Description:   The file holds the serial number of the client device obtained
                using a BHI (Boot Host Interface) register read after at least
                one attempt to power up the device has been done. If read
@@ -12,7 +12,7 @@ Users:                Any userspace application or clients interested in device info.
 What:          /sys/bus/mhi/devices/.../oem_pk_hash
 Date:          Sept 2020
 KernelVersion: 5.10
-Contact:       Bhaumik Bhatt <bbhatt@codeaurora.org>
+Contact:       mhi@lists.linux.dev
 Description:   The file holds the OEM PK Hash value of the endpoint device
                obtained using a BHI (Boot Host Interface) register read after
                at least one attempt to power up the device has been done. If
index d2a19b0..edc0ec5 100644 (file)
@@ -365,12 +365,10 @@ error_alloc_mhi_buf:
 }
 
 static void mhi_firmware_copy(struct mhi_controller *mhi_cntrl,
-                             const struct firmware *firmware,
+                             const u8 *buf, size_t remainder,
                              struct image_info *img_info)
 {
-       size_t remainder = firmware->size;
        size_t to_cpy;
-       const u8 *buf = firmware->data;
        struct mhi_buf *mhi_buf = img_info->mhi_buf;
        struct bhi_vec_entry *bhi_vec = img_info->bhi_vec;
 
@@ -393,9 +391,10 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
        struct device *dev = &mhi_cntrl->mhi_dev->dev;
        enum mhi_pm_state new_state;
        const char *fw_name;
+       const u8 *fw_data;
        void *buf;
        dma_addr_t dma_addr;
-       size_t size;
+       size_t size, fw_sz;
        int i, ret;
 
        if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
@@ -425,6 +424,20 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
        fw_name = (mhi_cntrl->ee == MHI_EE_EDL) ?
                mhi_cntrl->edl_image : mhi_cntrl->fw_image;
 
+       /* check if the driver has already provided the firmware data */
+       if (!fw_name && mhi_cntrl->fbc_download &&
+           mhi_cntrl->fw_data && mhi_cntrl->fw_sz) {
+               if (!mhi_cntrl->sbl_size) {
+                       dev_err(dev, "fw_data provided but no sbl_size\n");
+                       goto error_fw_load;
+               }
+
+               size = mhi_cntrl->sbl_size;
+               fw_data = mhi_cntrl->fw_data;
+               fw_sz = mhi_cntrl->fw_sz;
+               goto skip_req_fw;
+       }
+
        if (!fw_name || (mhi_cntrl->fbc_download && (!mhi_cntrl->sbl_size ||
                                                     !mhi_cntrl->seg_len))) {
                dev_err(dev,
@@ -444,6 +457,10 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
        if (size > firmware->size)
                size = firmware->size;
 
+       fw_data = firmware->data;
+       fw_sz = firmware->size;
+
+skip_req_fw:
        buf = dma_alloc_coherent(mhi_cntrl->cntrl_dev, size, &dma_addr,
                                 GFP_KERNEL);
        if (!buf) {
@@ -452,7 +469,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
        }
 
        /* Download image using BHI */
-       memcpy(buf, firmware->data, size);
+       memcpy(buf, fw_data, size);
        ret = mhi_fw_load_bhi(mhi_cntrl, dma_addr, size);
        dma_free_coherent(mhi_cntrl->cntrl_dev, size, buf, dma_addr);
 
@@ -464,7 +481,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
        }
 
        /* Wait for ready since EDL image was loaded */
-       if (fw_name == mhi_cntrl->edl_image) {
+       if (fw_name && fw_name == mhi_cntrl->edl_image) {
                release_firmware(firmware);
                goto fw_load_ready_state;
        }
@@ -478,15 +495,14 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
         * device transitioning into MHI READY state
         */
        if (mhi_cntrl->fbc_download) {
-               ret = mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image,
-                                          firmware->size);
+               ret = mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image, fw_sz);
                if (ret) {
                        release_firmware(firmware);
                        goto error_fw_load;
                }
 
                /* Load the firmware into BHIE vec table */
-               mhi_firmware_copy(mhi_cntrl, firmware, mhi_cntrl->fbc_image);
+               mhi_firmware_copy(mhi_cntrl, fw_data, fw_sz, mhi_cntrl->fbc_image);
        }
 
        release_firmware(firmware);
index f72fcb6..f78aefd 100644 (file)
@@ -759,7 +759,7 @@ static int parse_ch_cfg(struct mhi_controller *mhi_cntrl,
         * so to avoid any memory possible allocation failures, vzalloc is
         * used here
         */
-       mhi_cntrl->mhi_chan = vzalloc(mhi_cntrl->max_chan *
+       mhi_cntrl->mhi_chan = vcalloc(mhi_cntrl->max_chan,
                                      sizeof(*mhi_cntrl->mhi_chan));
        if (!mhi_cntrl->mhi_chan)
                return -ENOMEM;
index 74a7543..dcf627b 100644 (file)
@@ -938,7 +938,6 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,
                                if (!mhi_chan->configured)
                                        break;
                                parse_xfer_event(mhi_cntrl, local_rp, mhi_chan);
-                               event_quota--;
                        }
                        break;
                default:
index db0a0b0..08f3f03 100644 (file)
@@ -212,6 +212,19 @@ struct mhi_pci_dev_info {
                .offload_channel = false,       \
        }
 
+#define MHI_EVENT_CONFIG_SW_DATA(ev_ring, el_count) \
+       {                                       \
+               .num_elements = el_count,       \
+               .irq_moderation_ms = 0,         \
+               .irq = (ev_ring) + 1,           \
+               .priority = 1,                  \
+               .mode = MHI_DB_BRST_DISABLE,    \
+               .data_type = MHI_ER_DATA,       \
+               .hardware_event = false,        \
+               .client_managed = false,        \
+               .offload_channel = false,       \
+       }
+
 #define MHI_EVENT_CONFIG_HW_DATA(ev_ring, el_count, ch_num) \
        {                                       \
                .num_elements = el_count,       \
@@ -237,8 +250,10 @@ static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = {
        MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(21, "IPCR", 8, 0),
        MHI_CHANNEL_CONFIG_UL_FP(34, "FIREHOSE", 32, 0),
        MHI_CHANNEL_CONFIG_DL_FP(35, "FIREHOSE", 32, 0),
-       MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 2),
-       MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 3),
+       MHI_CHANNEL_CONFIG_UL(46, "IP_SW0", 64, 2),
+       MHI_CHANNEL_CONFIG_DL(47, "IP_SW0", 64, 3),
+       MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 4),
+       MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 5),
 };
 
 static struct mhi_event_config modem_qcom_v1_mhi_events[] = {
@@ -246,9 +261,12 @@ static struct mhi_event_config modem_qcom_v1_mhi_events[] = {
        MHI_EVENT_CONFIG_CTRL(0, 64),
        /* DIAG dedicated event ring */
        MHI_EVENT_CONFIG_DATA(1, 128),
+       /* Software channels dedicated event ring */
+       MHI_EVENT_CONFIG_SW_DATA(2, 64),
+       MHI_EVENT_CONFIG_SW_DATA(3, 64),
        /* Hardware channels request dedicated hardware event rings */
-       MHI_EVENT_CONFIG_HW_DATA(2, 1024, 100),
-       MHI_EVENT_CONFIG_HW_DATA(3, 2048, 101)
+       MHI_EVENT_CONFIG_HW_DATA(4, 1024, 100),
+       MHI_EVENT_CONFIG_HW_DATA(5, 2048, 101)
 };
 
 static const struct mhi_controller_config modem_qcom_v1_mhiv_config = {
@@ -334,6 +352,16 @@ static const struct mhi_pci_dev_info mhi_quectel_em1xx_info = {
        .sideband_wake = true,
 };
 
+static const struct mhi_pci_dev_info mhi_quectel_rm5xx_info = {
+       .name = "quectel-rm5xx",
+       .edl = "qcom/prog_firehose_sdx6x.elf",
+       .config = &modem_quectel_em1xx_config,
+       .bar_num = MHI_PCI_DEFAULT_BAR_NUM,
+       .dma_data_width = 32,
+       .mru_default = 32768,
+       .sideband_wake = true,
+};
+
 static const struct mhi_channel_config mhi_foxconn_sdx55_channels[] = {
        MHI_CHANNEL_CONFIG_UL(0, "LOOPBACK", 32, 0),
        MHI_CHANNEL_CONFIG_DL(1, "LOOPBACK", 32, 0),
@@ -567,12 +595,23 @@ static const struct pci_device_id mhi_pci_id_table[] = {
        /* Telit FN990 */
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0308, 0x1c5d, 0x2010),
                .driver_data = (kernel_ulong_t) &mhi_telit_fn990_info },
+       /* Telit FE990 */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0308, 0x1c5d, 0x2015),
+               .driver_data = (kernel_ulong_t) &mhi_telit_fn990_info },
        { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0308),
                .driver_data = (kernel_ulong_t) &mhi_qcom_sdx65_info },
        { PCI_DEVICE(PCI_VENDOR_ID_QUECTEL, 0x1001), /* EM120R-GL (sdx24) */
                .driver_data = (kernel_ulong_t) &mhi_quectel_em1xx_info },
        { PCI_DEVICE(PCI_VENDOR_ID_QUECTEL, 0x1002), /* EM160R-GL (sdx24) */
                .driver_data = (kernel_ulong_t) &mhi_quectel_em1xx_info },
+       /* RM520N-GL (sdx6x), eSIM */
+       { PCI_DEVICE(PCI_VENDOR_ID_QUECTEL, 0x1004),
+               .driver_data = (kernel_ulong_t) &mhi_quectel_rm5xx_info },
+       /* RM520N-GL (sdx6x), Lenovo variant */
+       { PCI_DEVICE(PCI_VENDOR_ID_QUECTEL, 0x1007),
+               .driver_data = (kernel_ulong_t) &mhi_quectel_rm5xx_info },
+       { PCI_DEVICE(PCI_VENDOR_ID_QUECTEL, 0x100d), /* EM160R-GL (sdx24) */
+               .driver_data = (kernel_ulong_t) &mhi_quectel_em1xx_info },
        { PCI_DEVICE(PCI_VENDOR_ID_QUECTEL, 0x2001), /* EM120R-GL for FCCL (sdx24) */
                .driver_data = (kernel_ulong_t) &mhi_quectel_em1xx_info },
        /* T99W175 (sdx55), Both for eSIM and Non-eSIM */
@@ -605,6 +644,12 @@ static const struct pci_device_id mhi_pci_id_table[] = {
        /* T99W510 (sdx24), variant 3 */
        { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0f2),
                .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx24_info },
+       /* DW5932e-eSIM (sdx62), With eSIM */
+       { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0f5),
+               .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx65_info },
+       /* DW5932e (sdx62), Non-eSIM */
+       { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0f9),
+               .driver_data = (kernel_ulong_t) &mhi_foxconn_sdx65_info },
        /* MV31-W (Cinterion) */
        { PCI_DEVICE(PCI_VENDOR_ID_THALES, 0x00b3),
                .driver_data = (kernel_ulong_t) &mhi_mv31_info },
index 0834590..8a4362d 100644 (file)
@@ -470,6 +470,10 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl)
 
        /* Trigger MHI RESET so that the device will not access host memory */
        if (!MHI_PM_IN_FATAL_STATE(mhi_cntrl->pm_state)) {
+               /* Skip MHI RESET if in RDDM state */
+               if (mhi_cntrl->rddm_image && mhi_get_exec_env(mhi_cntrl) == MHI_EE_RDDM)
+                       goto skip_mhi_reset;
+
                dev_dbg(dev, "Triggering MHI Reset in device\n");
                mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET);
 
@@ -495,6 +499,7 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl)
                }
        }
 
+skip_mhi_reset:
        dev_dbg(dev,
                 "Waiting for all pending event ring processing to complete\n");
        mhi_event = mhi_cntrl->mhi_event;
index f6de4b6..039943e 100644 (file)
@@ -299,6 +299,10 @@ struct mhi_controller_config {
  * @iova_start: IOMMU starting address for data (required)
  * @iova_stop: IOMMU stop address for data (required)
  * @fw_image: Firmware image name for normal booting (optional)
+ * @fw_data: Firmware image data content for normal booting, used only
+ *           if fw_image is NULL and fbc_download is true (optional)
+ * @fw_sz: Firmware image data size for normal booting, used only if fw_image
+ *         is NULL and fbc_download is true (optional)
  * @edl_image: Firmware image name for emergency download mode (optional)
  * @rddm_size: RAM dump size that host should allocate for debugging purpose
  * @sbl_size: SBL image size downloaded through BHIe (optional)
@@ -384,6 +388,8 @@ struct mhi_controller {
        dma_addr_t iova_start;
        dma_addr_t iova_stop;
        const char *fw_image;
+       const u8 *fw_data;
+       size_t fw_sz;
        const char *edl_image;
        size_t rddm_size;
        size_t sbl_size;