diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-04-03 13:56:03 +0200 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-04-03 13:56:03 +0200 |
| commit | 68c6d134edbf085ce63038b630c63f056279225a (patch) | |
| tree | 3e465784f9fa321f98f830efc7488bac45ccf8a3 | |
| parent | 94e731cbe84533a37701b4089b685d39e584fbea (diff) | |
| parent | ac12b852b4ead4a586299c8f68cdcbcaf1bf6cbc (diff) | |
Merge tag 'mhi-for-v7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/mani/mhi into char-misc-next
Manivannan writes:
MHI Host
--------
- Add support for Qualcomm SDX35 and Telit FE912C04 modems reusing the existing
channel and event configurations.
- Enable IP_SW and IP_ETH MHI channels for Qualcomm 5G DU X100 Accelerator
device (QDU100). These channels are used to carry O-RAN specific M-Plane,
S-Plane and Netconf packets. The drivers making use of these channels is being
reviewed.
- Add NMEA channels to Telit FN920C04 and FN990A modems for GPS/GNSS support
- Switch to mhi_async_power_up() API in pci_generic driver to avoid boot delays
as some Qcom modems take a while start. This API ensures that the pci_generic
driver powers up the modem asynchronously and doesn't block the system boot.
- Add pm_runtime_forbid() in remove callback to balance the pm_runtime_allow()
call made during the Mission Mode transition.
- Used kzalloc_flex() to simplify kzalloc() + kzalloc() calls
MHI Endpoint
------------
- Test for non-zero return value 'if (ret)' in the endpoint stack where
applicable to maintain code uniformity.
* tag 'mhi-for-v7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/mani/mhi:
bus: mhi: host: pci_generic: Add Telit FE912C04 modem support
bus: mhi: ep: Test for non-zero return value where applicable
bus: mhi: host: Use kzalloc_flex
bus: mhi: host: pci_generic: Add pm_runtime_forbid() in remove callback
bus: mhi: host: pci_generic: Switch to async power up to avoid boot delays
bus: mhi: host: pci_generic: Add NMEA channels to FN920C04 and FN990A
bus: mhi: host: pci_generic: Enable IP_SW and IP_ETH channels for Qcom QDU100 device
bus: mhi: host: pci_generic: Add Qualcomm SDX35 modem
| -rw-r--r-- | drivers/bus/mhi/ep/main.c | 10 | ||||
| -rw-r--r-- | drivers/bus/mhi/ep/ring.c | 6 | ||||
| -rw-r--r-- | drivers/bus/mhi/host/boot.c | 22 | ||||
| -rw-r--r-- | drivers/bus/mhi/host/pci_generic.c | 40 | ||||
| -rw-r--r-- | include/linux/mhi.h | 34 |
5 files changed, 67 insertions, 45 deletions
diff --git a/drivers/bus/mhi/ep/main.c b/drivers/bus/mhi/ep/main.c index e3d0a3cbaf94..0277e1ab1198 100644 --- a/drivers/bus/mhi/ep/main.c +++ b/drivers/bus/mhi/ep/main.c @@ -367,7 +367,7 @@ static void mhi_ep_read_completion(struct mhi_ep_buf_info *buf_info) ret = mhi_ep_send_completion_event(mhi_cntrl, ring, el, MHI_TRE_DATA_GET_LEN(el), MHI_EV_CC_EOB); - if (ret < 0) { + if (ret) { dev_err(&mhi_chan->mhi_dev->dev, "Error sending transfer compl. event\n"); goto err_free_tre_buf; @@ -383,7 +383,7 @@ static void mhi_ep_read_completion(struct mhi_ep_buf_info *buf_info) ret = mhi_ep_send_completion_event(mhi_cntrl, ring, el, MHI_TRE_DATA_GET_LEN(el), MHI_EV_CC_EOT); - if (ret < 0) { + if (ret) { dev_err(&mhi_chan->mhi_dev->dev, "Error sending transfer compl. event\n"); goto err_free_tre_buf; @@ -449,7 +449,7 @@ static int mhi_ep_read_channel(struct mhi_ep_cntrl *mhi_cntrl, dev_dbg(dev, "Reading %zd bytes from channel (%u)\n", tr_len, ring->ch_id); ret = mhi_cntrl->read_async(mhi_cntrl, &buf_info); - if (ret < 0) { + if (ret) { dev_err(&mhi_chan->mhi_dev->dev, "Error reading from channel\n"); goto err_free_buf_addr; } @@ -494,7 +494,7 @@ static int mhi_ep_process_ch_ring(struct mhi_ep_ring *ring) } else { /* UL channel */ ret = mhi_ep_read_channel(mhi_cntrl, ring); - if (ret < 0) { + if (ret) { dev_err(&mhi_chan->mhi_dev->dev, "Failed to read channel\n"); return ret; } @@ -591,7 +591,7 @@ int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, struct sk_buff *skb) dev_dbg(dev, "Writing %zd bytes to channel (%u)\n", tr_len, ring->ch_id); ret = mhi_cntrl->write_async(mhi_cntrl, &buf_info); - if (ret < 0) { + if (ret) { dev_err(dev, "Error writing to the channel\n"); goto err_exit; } diff --git a/drivers/bus/mhi/ep/ring.c b/drivers/bus/mhi/ep/ring.c index 9375b16ff2a5..405ce16c02a8 100644 --- a/drivers/bus/mhi/ep/ring.c +++ b/drivers/bus/mhi/ep/ring.c @@ -49,7 +49,7 @@ static int __mhi_ep_cache_ring(struct mhi_ep_ring *ring, size_t end) buf_info.dev_addr = &ring->ring_cache[start]; ret = mhi_cntrl->read_sync(mhi_cntrl, &buf_info); - if (ret < 0) + if (ret) return ret; } else { buf_info.size = (ring->ring_size - start) * sizeof(struct mhi_ring_element); @@ -57,7 +57,7 @@ static int __mhi_ep_cache_ring(struct mhi_ep_ring *ring, size_t end) buf_info.dev_addr = &ring->ring_cache[start]; ret = mhi_cntrl->read_sync(mhi_cntrl, &buf_info); - if (ret < 0) + if (ret) return ret; if (end) { @@ -66,7 +66,7 @@ static int __mhi_ep_cache_ring(struct mhi_ep_ring *ring, size_t end) buf_info.size = end * sizeof(struct mhi_ring_element); ret = mhi_cntrl->read_sync(mhi_cntrl, &buf_info); - if (ret < 0) + if (ret) return ret; } } diff --git a/drivers/bus/mhi/host/boot.c b/drivers/bus/mhi/host/boot.c index f16a1e67a667..19c84913cfb9 100644 --- a/drivers/bus/mhi/host/boot.c +++ b/drivers/bus/mhi/host/boot.c @@ -308,7 +308,6 @@ static void mhi_free_bhi_buffer(struct mhi_controller *mhi_cntrl, struct mhi_buf *mhi_buf = image_info->mhi_buf; dma_free_coherent(mhi_cntrl->cntrl_dev, mhi_buf->len, mhi_buf->buf, mhi_buf->dma_addr); - kfree(image_info->mhi_buf); kfree(image_info); } @@ -322,7 +321,6 @@ void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl, dma_free_coherent(mhi_cntrl->cntrl_dev, mhi_buf->len, mhi_buf->buf, mhi_buf->dma_addr); - kfree(image_info->mhi_buf); kfree(image_info); } @@ -333,15 +331,10 @@ static int mhi_alloc_bhi_buffer(struct mhi_controller *mhi_cntrl, struct image_info *img_info; struct mhi_buf *mhi_buf; - img_info = kzalloc_obj(*img_info); + img_info = kzalloc_flex(*img_info, mhi_buf, 1); if (!img_info) return -ENOMEM; - /* Allocate memory for entry */ - img_info->mhi_buf = kzalloc_obj(*img_info->mhi_buf); - if (!img_info->mhi_buf) - goto error_alloc_mhi_buf; - /* Allocate and populate vector table */ mhi_buf = img_info->mhi_buf; @@ -358,8 +351,6 @@ static int mhi_alloc_bhi_buffer(struct mhi_controller *mhi_cntrl, return 0; error_alloc_segment: - kfree(mhi_buf); -error_alloc_mhi_buf: kfree(img_info); return -ENOMEM; @@ -375,14 +366,11 @@ int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, struct image_info *img_info; struct mhi_buf *mhi_buf; - img_info = kzalloc_obj(*img_info); + img_info = kzalloc_flex(*img_info, mhi_buf, segments); if (!img_info) return -ENOMEM; - /* Allocate memory for entries */ - img_info->mhi_buf = kzalloc_objs(*img_info->mhi_buf, segments); - if (!img_info->mhi_buf) - goto error_alloc_mhi_buf; + img_info->entries = segments; /* Allocate and populate vector table */ mhi_buf = img_info->mhi_buf; @@ -402,7 +390,6 @@ int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, } img_info->bhi_vec = img_info->mhi_buf[segments - 1].buf; - img_info->entries = segments; *image_info = img_info; return 0; @@ -411,9 +398,6 @@ error_alloc_segment: for (--i, --mhi_buf; i >= 0; i--, mhi_buf--) dma_free_coherent(mhi_cntrl->cntrl_dev, mhi_buf->len, mhi_buf->buf, mhi_buf->dma_addr); - kfree(img_info->mhi_buf); - -error_alloc_mhi_buf: kfree(img_info); return -ENOMEM; diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c index 0884a384b77f..750da3dbb4c6 100644 --- a/drivers/bus/mhi/host/pci_generic.c +++ b/drivers/bus/mhi/host/pci_generic.c @@ -253,6 +253,13 @@ static const struct mhi_channel_config mhi_qcom_qdu100_channels[] = { MHI_CHANNEL_CONFIG_DL(41, "MHI_PHC", 32, 4), MHI_CHANNEL_CONFIG_UL(46, "IP_SW0", 256, 5), MHI_CHANNEL_CONFIG_DL(47, "IP_SW0", 256, 5), + MHI_CHANNEL_CONFIG_UL(48, "IP_SW1", 256, 6), + MHI_CHANNEL_CONFIG_DL(49, "IP_SW1", 256, 6), + MHI_CHANNEL_CONFIG_UL(50, "IP_ETH0", 256, 7), + MHI_CHANNEL_CONFIG_DL(51, "IP_ETH0", 256, 7), + MHI_CHANNEL_CONFIG_UL(52, "IP_ETH1", 256, 8), + MHI_CHANNEL_CONFIG_DL(53, "IP_ETH1", 256, 8), + }; static struct mhi_event_config mhi_qcom_qdu100_events[] = { @@ -268,6 +275,7 @@ static struct mhi_event_config mhi_qcom_qdu100_events[] = { MHI_EVENT_CONFIG_SW_DATA(5, 512), MHI_EVENT_CONFIG_SW_DATA(6, 512), MHI_EVENT_CONFIG_SW_DATA(7, 512), + MHI_EVENT_CONFIG_SW_DATA(8, 512), }; static const struct mhi_controller_config mhi_qcom_qdu100_config = { @@ -407,6 +415,16 @@ static const struct mhi_pci_dev_info mhi_qcom_sdx55_info = { .sideband_wake = false, }; +static const struct mhi_pci_dev_info mhi_qcom_sdx35_info = { + .name = "qcom-sdx35m", + .config = &modem_qcom_v2_mhiv_config, + .bar_num = MHI_PCI_DEFAULT_BAR_NUM, + .dma_data_width = 32, + .mru_default = 32768, + .sideband_wake = false, + .edl_trigger = true, +}; + static const struct mhi_pci_dev_info mhi_qcom_sdx24_info = { .name = "qcom-sdx24", .edl = "qcom/prog_firehose_sdx24.mbn", @@ -788,6 +806,8 @@ static const struct mhi_channel_config mhi_telit_fn990_channels[] = { MHI_CHANNEL_CONFIG_DL(33, "DUN", 32, 0), MHI_CHANNEL_CONFIG_UL(92, "DUN2", 32, 1), MHI_CHANNEL_CONFIG_DL(93, "DUN2", 32, 1), + MHI_CHANNEL_CONFIG_UL(94, "NMEA", 32, 1), + MHI_CHANNEL_CONFIG_DL(95, "NMEA", 32, 1), MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0_MBIM", 128, 2), MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0_MBIM", 128, 3), }; @@ -839,6 +859,8 @@ static const struct mhi_channel_config mhi_telit_fn920c04_channels[] = { MHI_CHANNEL_CONFIG_DL_FP(35, "FIREHOSE", 32, 0), MHI_CHANNEL_CONFIG_UL(92, "DUN2", 32, 1), MHI_CHANNEL_CONFIG_DL(93, "DUN2", 32, 1), + MHI_CHANNEL_CONFIG_UL(94, "NMEA", 32, 1), + MHI_CHANNEL_CONFIG_DL(95, "NMEA", 32, 1), MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 2), MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 3), }; @@ -882,6 +904,16 @@ static const struct mhi_pci_dev_info mhi_telit_fe990b40_info = { .edl_trigger = true, }; +static const struct mhi_pci_dev_info mhi_telit_fe912c04_info = { + .name = "telit-fe912c04", + .config = &modem_telit_fn920c04_config, + .bar_num = MHI_PCI_DEFAULT_BAR_NUM, + .dma_data_width = 32, + .sideband_wake = false, + .mru_default = 32768, + .edl_trigger = true, +}; + static const struct mhi_pci_dev_info mhi_netprisma_lcur57_info = { .name = "netprisma-lcur57", .edl = "qcom/prog_firehose_sdx24.mbn", @@ -909,6 +941,11 @@ static const struct pci_device_id mhi_pci_id_table[] = { /* Telit FN920C04 (sdx35) */ {PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x011a, 0x1c5d, 0x2020), .driver_data = (kernel_ulong_t) &mhi_telit_fn920c04_info }, + /* Telit FE912C04 (sdx35) */ + { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x011a, 0x1c5d, 0x2045), + .driver_data = (kernel_ulong_t) &mhi_telit_fe912c04_info }, + { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x011a), + .driver_data = (kernel_ulong_t) &mhi_qcom_sdx35_info }, { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0304), .driver_data = (kernel_ulong_t) &mhi_qcom_sdx24_info }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0306, PCI_VENDOR_ID_QCOM, 0x010c), @@ -1393,7 +1430,7 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_unregister; } - err = mhi_sync_power_up(mhi_cntrl); + err = mhi_async_power_up(mhi_cntrl); if (err) { dev_err(&pdev->dev, "failed to power up MHI controller\n"); goto err_unprepare; @@ -1428,6 +1465,7 @@ static void mhi_pci_remove(struct pci_dev *pdev) struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev); struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl; + pm_runtime_forbid(&pdev->dev); pci_disable_sriov(pdev); if (pdev->is_physfn) diff --git a/include/linux/mhi.h b/include/linux/mhi.h index 88ccb3e14f48..fb3ba639f4f8 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -86,16 +86,32 @@ enum mhi_ch_type { }; /** + * struct mhi_buf - MHI Buffer description + * @buf: Virtual address of the buffer + * @name: Buffer label. For offload channel, configurations name must be: + * ECA - Event context array data + * CCA - Channel context array data + * @dma_addr: IOMMU address of the buffer + * @len: # of bytes + */ +struct mhi_buf { + void *buf; + const char *name; + dma_addr_t dma_addr; + size_t len; +}; + +/** * struct image_info - Firmware and RDDM table * @mhi_buf: Buffer for firmware and RDDM table * @entries: # of entries in table */ struct image_info { - struct mhi_buf *mhi_buf; /* private: from internal.h */ struct bhi_vec_entry *bhi_vec; /* public: */ u32 entries; + struct mhi_buf mhi_buf[] __counted_by(entries); }; /** @@ -489,22 +505,6 @@ struct mhi_result { }; /** - * struct mhi_buf - MHI Buffer description - * @buf: Virtual address of the buffer - * @name: Buffer label. For offload channel, configurations name must be: - * ECA - Event context array data - * CCA - Channel context array data - * @dma_addr: IOMMU address of the buffer - * @len: # of bytes - */ -struct mhi_buf { - void *buf; - const char *name; - dma_addr_t dma_addr; - size_t len; -}; - -/** * struct mhi_driver - Structure representing a MHI client driver * @probe: CB function for client driver probe function * @remove: CB function for client driver remove function |
