RE: MHI code review
Our team also monitoring following thread https://lkml.kernel.org/lkml/20190531035348.7194-1-el...@linaro.org/ Since this also has implication on MHI as well. Thanks Sujeev -Original Message- From: Sujeev Dias Sent: Wednesday, June 12, 2019 10:55 AM To: 'Daniele Palmas' Cc: 'linux-kernel@vger.kernel.org' ; 'tru...@codeaurora.org' Subject: RE: MHI code review Hi Daniels Sorry for delay response. Yes, we will be pushing new set of series very soon that will have support for 55 as well. The series that's pushed should already work for SDX20, 24 and 55. There are some new features related to 55 that's not yet in series. Thanks Sujeev -Original Message- From: Daniele Palmas Sent: Tuesday, April 30, 2019 8:11 AM To: sd...@codeaurora.org Cc: linux-kernel@vger.kernel.org; tru...@codeaurora.org; dnl...@gmail.com Subject: Re: MHI code review Hi Sujeev, > Hi Greg Kroah-Hartman\Arnd Bergmann and community > > Thank you for all the feedback, I believe I have addressed all the > comments from previous patches. Also, I am excluding mhi network > driver in this series. I still have some modifications to do. > > Please review the new patch series and share your feedback. > > Thanks again > > Sincerely, > Sujeev are you going to continue working on this series? Can this series be used with PCIe SDX20/24/55 based modems? If yes, it would really be important to have this integrated into an official kernel. Thanks, Daniele
RE: MHI code review
Hi Daniels Sorry for delay response. Yes, we will be pushing new set of series very soon that will have support for 55 as well. The series that's pushed should already work for SDX20, 24 and 55. There are some new features related to 55 that's not yet in series. Thanks Sujeev -Original Message- From: Daniele Palmas Sent: Tuesday, April 30, 2019 8:11 AM To: sd...@codeaurora.org Cc: linux-kernel@vger.kernel.org; tru...@codeaurora.org; dnl...@gmail.com Subject: Re: MHI code review Hi Sujeev, > Hi Greg Kroah-Hartman\Arnd Bergmann and community > > Thank you for all the feedback, I believe I have addressed all the > comments from previous patches. Also, I am excluding mhi network > driver in this series. I still have some modifications to do. > > Please review the new patch series and share your feedback. > > Thanks again > > Sincerely, > Sujeev are you going to continue working on this series? Can this series be used with PCIe SDX20/24/55 based modems? If yes, it would really be important to have this integrated into an official kernel. Thanks, Daniele
[PATCH v2 2/7] mhi_bus: core: add power management support
Add support for MHI power management operations such as power on, off, suspend, and resume. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- drivers/bus/mhi/core/Makefile |2 +- drivers/bus/mhi/core/mhi_boot.c | 533 ++ drivers/bus/mhi/core/mhi_init.c | 695 +++- drivers/bus/mhi/core/mhi_internal.h | 491 + drivers/bus/mhi/core/mhi_main.c | 528 +- drivers/bus/mhi/core/mhi_pm.c | 1027 +++ include/linux/mhi.h | 121 + 7 files changed, 3394 insertions(+), 3 deletions(-) create mode 100644 drivers/bus/mhi/core/mhi_boot.c create mode 100644 drivers/bus/mhi/core/mhi_pm.c diff --git a/drivers/bus/mhi/core/Makefile b/drivers/bus/mhi/core/Makefile index a015809..a6015ab 100644 --- a/drivers/bus/mhi/core/Makefile +++ b/drivers/bus/mhi/core/Makefile @@ -1 +1 @@ -obj-$(CONFIG_MHI_BUS) +=mhi_init.o mhi_main.o +obj-$(CONFIG_MHI_BUS) +=mhi_init.o mhi_main.o mhi_pm.o mhi_boot.o diff --git a/drivers/bus/mhi/core/mhi_boot.c b/drivers/bus/mhi/core/mhi_boot.c new file mode 100644 index 000..a8e4a15 --- /dev/null +++ b/drivers/bus/mhi/core/mhi_boot.c @@ -0,0 +1,533 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mhi_internal.h" + + +/* setup rddm vector table for rddm transfer */ +static void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, +struct image_info *img_info) +{ + struct mhi_buf *mhi_buf = img_info->mhi_buf; + struct bhi_vec_entry *bhi_vec = img_info->bhi_vec; + int i = 0; + + for (i = 0; i < img_info->entries - 1; i++, mhi_buf++, bhi_vec++) { + bhi_vec->dma_addr = mhi_buf->dma_addr; + bhi_vec->size = mhi_buf->len; + } +} + +/* collect rddm during kernel panic */ +static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) +{ + int ret; + struct mhi_buf *mhi_buf; + u32 sequence_id; + u32 rx_status; + enum MHI_EE ee; + struct image_info *rddm_image = mhi_cntrl->rddm_image; + const u32 delayus = 100; + u32 retry = (mhi_cntrl->timeout_ms * 1000) / delayus; + void __iomem *base = mhi_cntrl->bhie; + + dev_info(mhi_cntrl->dev, +"Entered with pm_state:%s dev_state:%s ee:%s\n", + to_mhi_pm_state_str(mhi_cntrl->pm_state), + TO_MHI_STATE_STR(mhi_cntrl->dev_state), + TO_MHI_EXEC_STR(mhi_cntrl->ee)); + + /* +* This should only be executing during a kernel panic, we expect all +* other cores to shutdown while we're collecting rddm buffer. After +* returning from this function, we expect device to reset. +* +* Normaly, we would read/write pm_state only after grabbing +* pm_lock, since we're in a panic, skipping it. +*/ + + if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) + return -EIO; + + /* +* There is no gurantee this state change would take effect since +* we're setting it w/o grabbing pmlock, it's best effort +*/ + mhi_cntrl->pm_state = MHI_PM_LD_ERR_FATAL_DETECT; + /* update should take the effect immediately */ + smp_wmb(); + + /* setup the RX vector table */ + mhi_rddm_prepare(mhi_cntrl, rddm_image); + mhi_buf = _image->mhi_buf[rddm_image->entries - 1]; + + mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS, + upper_32_bits(mhi_buf->dma_addr)); + + mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS, + lower_32_bits(mhi_buf->dma_addr)); + + mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); + sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; + + if (unlikely(!sequence_id)) + sequence_id = 1; + + + mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS, + BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT, + sequence_id); + + mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR); + + while (retry--) { + ret = mhi_read_reg_field(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, +BHIE_RXVECSTATUS_STATUS_BMSK, +BHIE_RXVECSTATUS_STATUS_SHFT, +_status); + if (ret) + return -EIO; + + if (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) + return 0; + +
[PATCH v2 3/7] mhi_bus: core: add support for data transfer
Add support for transferring data between external modem and MHI host using MHI protocol. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- drivers/bus/mhi/core/mhi_init.c | 76 +++- drivers/bus/mhi/core/mhi_internal.h | 8 - drivers/bus/mhi/core/mhi_main.c | 803 +++- include/linux/mhi.h | 78 4 files changed, 950 insertions(+), 15 deletions(-) diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index 7b3d12a..43a700d 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -548,6 +548,66 @@ int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl, return 0; } +int mhi_device_configure(struct mhi_device *mhi_dev, +enum dma_data_direction dir, +struct mhi_buf *cfg_tbl, +int elements) +{ + struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; + struct mhi_chan *mhi_chan; + struct mhi_event_ctxt *er_ctxt; + struct mhi_chan_ctxt *ch_ctxt; + int er_index, chan; + + switch (dir) { + case DMA_TO_DEVICE: + mhi_chan = mhi_dev->ul_chan; + break; + case DMA_BIDIRECTIONAL: + case DMA_FROM_DEVICE: + case DMA_NONE: + mhi_chan = mhi_dev->dl_chan; + break; + default: + return -EINVAL; + } + + er_index = mhi_chan->er_index; + chan = mhi_chan->chan; + + for (; elements > 0; elements--, cfg_tbl++) { + /* update event context array */ + if (!strcmp(cfg_tbl->name, "ECA")) { + er_ctxt = _cntrl->mhi_ctxt->er_ctxt[er_index]; + if (sizeof(*er_ctxt) != cfg_tbl->len) { + dev_err(mhi_cntrl->dev, + "Invalid ECA size, expected:%zu actual%zu\n", + sizeof(*er_ctxt), cfg_tbl->len); + return -EINVAL; + } + memcpy((void *)er_ctxt, cfg_tbl->buf, sizeof(*er_ctxt)); + continue; + } + + /* update channel context array */ + if (!strcmp(cfg_tbl->name, "CCA")) { + ch_ctxt = _cntrl->mhi_ctxt->chan_ctxt[chan]; + if (cfg_tbl->len != sizeof(*ch_ctxt)) { + dev_err(mhi_cntrl->dev, + "Invalid CCA size, expected:%zu actual:%zu\n", + sizeof(*ch_ctxt), cfg_tbl->len); + return -EINVAL; + } + memcpy((void *)ch_ctxt, cfg_tbl->buf, sizeof(*ch_ctxt)); + continue; + } + + return -EINVAL; + } + + return 0; +} + static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl, struct device_node *of_node) { @@ -1067,6 +1127,9 @@ static int mhi_driver_probe(struct device *dev) struct mhi_event *mhi_event; struct mhi_chan *ul_chan = mhi_dev->ul_chan; struct mhi_chan *dl_chan = mhi_dev->dl_chan; + bool auto_start = false; + int ret; + if (ul_chan) { /* lpm notification require status_cb */ @@ -1078,6 +1141,7 @@ static int mhi_driver_probe(struct device *dev) ul_chan->xfer_cb = mhi_drv->ul_xfer_cb; mhi_dev->status_cb = mhi_drv->status_cb; + auto_start = ul_chan->auto_start; } if (dl_chan) { @@ -1101,9 +1165,15 @@ static int mhi_driver_probe(struct device *dev) /* ul & dl uses same status cb */ mhi_dev->status_cb = mhi_drv->status_cb; + auto_start = (auto_start || dl_chan->auto_start); } - return mhi_drv->probe(mhi_dev, mhi_dev->id); + ret = mhi_drv->probe(mhi_dev, mhi_dev->id); + + if (!ret && auto_start) + mhi_prepare_for_transfer(mhi_dev); + + return ret; } static int mhi_driver_remove(struct device *dev) @@ -1141,6 +1211,10 @@ static int mhi_driver_remove(struct device *dev) ch_state[dir] = mhi_chan->ch_state; mhi_chan->ch_state = MHI_CH_STATE_DISABLED; write_unlock_irq(_chan->lock); + + /* reset the channel */ + if (!mhi_chan->offload_ch) + mhi_reset_chan(mhi_cntrl, mhi_chan); } /* destroy the device */ diff --git a/drivers/bus/mhi/core/mhi_internal.h b/drivers/bus/mhi/core/mhi_internal.h index 0091245..1167d75 100644 --- a/drivers/bus/mhi
[PATCH v2 2/7] mhi_bus: core: add power management support
Add support for MHI power management operations such as power on, off, suspend, and resume. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- drivers/bus/mhi/core/Makefile |2 +- drivers/bus/mhi/core/mhi_boot.c | 533 ++ drivers/bus/mhi/core/mhi_init.c | 695 +++- drivers/bus/mhi/core/mhi_internal.h | 491 + drivers/bus/mhi/core/mhi_main.c | 528 +- drivers/bus/mhi/core/mhi_pm.c | 1027 +++ include/linux/mhi.h | 121 + 7 files changed, 3394 insertions(+), 3 deletions(-) create mode 100644 drivers/bus/mhi/core/mhi_boot.c create mode 100644 drivers/bus/mhi/core/mhi_pm.c diff --git a/drivers/bus/mhi/core/Makefile b/drivers/bus/mhi/core/Makefile index a015809..a6015ab 100644 --- a/drivers/bus/mhi/core/Makefile +++ b/drivers/bus/mhi/core/Makefile @@ -1 +1 @@ -obj-$(CONFIG_MHI_BUS) +=mhi_init.o mhi_main.o +obj-$(CONFIG_MHI_BUS) +=mhi_init.o mhi_main.o mhi_pm.o mhi_boot.o diff --git a/drivers/bus/mhi/core/mhi_boot.c b/drivers/bus/mhi/core/mhi_boot.c new file mode 100644 index 000..a8e4a15 --- /dev/null +++ b/drivers/bus/mhi/core/mhi_boot.c @@ -0,0 +1,533 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mhi_internal.h" + + +/* setup rddm vector table for rddm transfer */ +static void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, +struct image_info *img_info) +{ + struct mhi_buf *mhi_buf = img_info->mhi_buf; + struct bhi_vec_entry *bhi_vec = img_info->bhi_vec; + int i = 0; + + for (i = 0; i < img_info->entries - 1; i++, mhi_buf++, bhi_vec++) { + bhi_vec->dma_addr = mhi_buf->dma_addr; + bhi_vec->size = mhi_buf->len; + } +} + +/* collect rddm during kernel panic */ +static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) +{ + int ret; + struct mhi_buf *mhi_buf; + u32 sequence_id; + u32 rx_status; + enum MHI_EE ee; + struct image_info *rddm_image = mhi_cntrl->rddm_image; + const u32 delayus = 100; + u32 retry = (mhi_cntrl->timeout_ms * 1000) / delayus; + void __iomem *base = mhi_cntrl->bhie; + + dev_info(mhi_cntrl->dev, +"Entered with pm_state:%s dev_state:%s ee:%s\n", + to_mhi_pm_state_str(mhi_cntrl->pm_state), + TO_MHI_STATE_STR(mhi_cntrl->dev_state), + TO_MHI_EXEC_STR(mhi_cntrl->ee)); + + /* +* This should only be executing during a kernel panic, we expect all +* other cores to shutdown while we're collecting rddm buffer. After +* returning from this function, we expect device to reset. +* +* Normaly, we would read/write pm_state only after grabbing +* pm_lock, since we're in a panic, skipping it. +*/ + + if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) + return -EIO; + + /* +* There is no gurantee this state change would take effect since +* we're setting it w/o grabbing pmlock, it's best effort +*/ + mhi_cntrl->pm_state = MHI_PM_LD_ERR_FATAL_DETECT; + /* update should take the effect immediately */ + smp_wmb(); + + /* setup the RX vector table */ + mhi_rddm_prepare(mhi_cntrl, rddm_image); + mhi_buf = _image->mhi_buf[rddm_image->entries - 1]; + + mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS, + upper_32_bits(mhi_buf->dma_addr)); + + mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS, + lower_32_bits(mhi_buf->dma_addr)); + + mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); + sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; + + if (unlikely(!sequence_id)) + sequence_id = 1; + + + mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS, + BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT, + sequence_id); + + mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR); + + while (retry--) { + ret = mhi_read_reg_field(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, +BHIE_RXVECSTATUS_STATUS_BMSK, +BHIE_RXVECSTATUS_STATUS_SHFT, +_status); + if (ret) + return -EIO; + + if (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) + return 0; + +
[PATCH v2 3/7] mhi_bus: core: add support for data transfer
Add support for transferring data between external modem and MHI host using MHI protocol. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- drivers/bus/mhi/core/mhi_init.c | 76 +++- drivers/bus/mhi/core/mhi_internal.h | 8 - drivers/bus/mhi/core/mhi_main.c | 803 +++- include/linux/mhi.h | 78 4 files changed, 950 insertions(+), 15 deletions(-) diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index 7b3d12a..43a700d 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -548,6 +548,66 @@ int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl, return 0; } +int mhi_device_configure(struct mhi_device *mhi_dev, +enum dma_data_direction dir, +struct mhi_buf *cfg_tbl, +int elements) +{ + struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; + struct mhi_chan *mhi_chan; + struct mhi_event_ctxt *er_ctxt; + struct mhi_chan_ctxt *ch_ctxt; + int er_index, chan; + + switch (dir) { + case DMA_TO_DEVICE: + mhi_chan = mhi_dev->ul_chan; + break; + case DMA_BIDIRECTIONAL: + case DMA_FROM_DEVICE: + case DMA_NONE: + mhi_chan = mhi_dev->dl_chan; + break; + default: + return -EINVAL; + } + + er_index = mhi_chan->er_index; + chan = mhi_chan->chan; + + for (; elements > 0; elements--, cfg_tbl++) { + /* update event context array */ + if (!strcmp(cfg_tbl->name, "ECA")) { + er_ctxt = _cntrl->mhi_ctxt->er_ctxt[er_index]; + if (sizeof(*er_ctxt) != cfg_tbl->len) { + dev_err(mhi_cntrl->dev, + "Invalid ECA size, expected:%zu actual%zu\n", + sizeof(*er_ctxt), cfg_tbl->len); + return -EINVAL; + } + memcpy((void *)er_ctxt, cfg_tbl->buf, sizeof(*er_ctxt)); + continue; + } + + /* update channel context array */ + if (!strcmp(cfg_tbl->name, "CCA")) { + ch_ctxt = _cntrl->mhi_ctxt->chan_ctxt[chan]; + if (cfg_tbl->len != sizeof(*ch_ctxt)) { + dev_err(mhi_cntrl->dev, + "Invalid CCA size, expected:%zu actual:%zu\n", + sizeof(*ch_ctxt), cfg_tbl->len); + return -EINVAL; + } + memcpy((void *)ch_ctxt, cfg_tbl->buf, sizeof(*ch_ctxt)); + continue; + } + + return -EINVAL; + } + + return 0; +} + static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl, struct device_node *of_node) { @@ -1067,6 +1127,9 @@ static int mhi_driver_probe(struct device *dev) struct mhi_event *mhi_event; struct mhi_chan *ul_chan = mhi_dev->ul_chan; struct mhi_chan *dl_chan = mhi_dev->dl_chan; + bool auto_start = false; + int ret; + if (ul_chan) { /* lpm notification require status_cb */ @@ -1078,6 +1141,7 @@ static int mhi_driver_probe(struct device *dev) ul_chan->xfer_cb = mhi_drv->ul_xfer_cb; mhi_dev->status_cb = mhi_drv->status_cb; + auto_start = ul_chan->auto_start; } if (dl_chan) { @@ -1101,9 +1165,15 @@ static int mhi_driver_probe(struct device *dev) /* ul & dl uses same status cb */ mhi_dev->status_cb = mhi_drv->status_cb; + auto_start = (auto_start || dl_chan->auto_start); } - return mhi_drv->probe(mhi_dev, mhi_dev->id); + ret = mhi_drv->probe(mhi_dev, mhi_dev->id); + + if (!ret && auto_start) + mhi_prepare_for_transfer(mhi_dev); + + return ret; } static int mhi_driver_remove(struct device *dev) @@ -1141,6 +1211,10 @@ static int mhi_driver_remove(struct device *dev) ch_state[dir] = mhi_chan->ch_state; mhi_chan->ch_state = MHI_CH_STATE_DISABLED; write_unlock_irq(_chan->lock); + + /* reset the channel */ + if (!mhi_chan->offload_ch) + mhi_reset_chan(mhi_cntrl, mhi_chan); } /* destroy the device */ diff --git a/drivers/bus/mhi/core/mhi_internal.h b/drivers/bus/mhi/core/mhi_internal.h index 0091245..1167d75 100644 --- a/drivers/bus/mhi
[PATCH v2 1/7] mhi_bus: core: initial checkin for modem host interface bus driver
This is the initial skeleton driver for mhi bus stack. MHI Host Interface is a communication protocol to be used by the host to control and communcate with modem over a high speed peripheral bus. This module will allow host to communicate with external devices that support MHI protocol. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- Documentation/00-INDEX| 2 + Documentation/devicetree/bindings/bus/mhi.txt | 258 Documentation/mhi.txt | 235 +++ drivers/bus/Kconfig | 8 + drivers/bus/Makefile | 1 + drivers/bus/mhi/Makefile | 6 + drivers/bus/mhi/core/Makefile | 1 + drivers/bus/mhi/core/mhi_init.c | 538 ++ drivers/bus/mhi/core/mhi_internal.h | 238 drivers/bus/mhi/core/mhi_main.c | 122 ++ include/linux/mhi.h | 341 include/linux/mod_devicetable.h | 12 + 12 files changed, 1762 insertions(+) create mode 100644 Documentation/devicetree/bindings/bus/mhi.txt create mode 100644 Documentation/mhi.txt create mode 100644 drivers/bus/mhi/Makefile create mode 100644 drivers/bus/mhi/core/Makefile create mode 100644 drivers/bus/mhi/core/mhi_init.c create mode 100644 drivers/bus/mhi/core/mhi_internal.h create mode 100644 drivers/bus/mhi/core/mhi_main.c create mode 100644 include/linux/mhi.h diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 708dc4c..44e2c6b 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -270,6 +270,8 @@ memory-hotplug.txt - Hotpluggable memory support, how to use and current status. men-chameleon-bus.txt - info on MEN chameleon bus. +mhi.txt + - Modem Host Interface mic/ - Intel Many Integrated Core (MIC) architecture device driver. mips/ diff --git a/Documentation/devicetree/bindings/bus/mhi.txt b/Documentation/devicetree/bindings/bus/mhi.txt new file mode 100644 index 000..19deb84 --- /dev/null +++ b/Documentation/devicetree/bindings/bus/mhi.txt @@ -0,0 +1,258 @@ +MHI Host Interface + +MHI used by the host to control and communicate with modem over +high speed peripheral bus. + +== +Node Structure +== + +Main node properties: + +- mhi,max-channels + Usage: required + Value type: + Definition: Maximum number of channels supported by this controller + +- mhi,timeout + Usage: optional + Value type: + Definition: Maximum timeout in ms wait for state and cmd completion + +- mhi,use-bb + Usage: optional + Value type: + Definition: Set true, if PCIe controller does not have full access to host + DDR, and we're using a dedicated memory pool like cma, or + carveout pool. Pool must support atomic allocation. + +- mhi,buffer-len + Usage: optional + Value type: + Definition: MHI automatically pre-allocate buffers for some channel. + Set the length of buffer size to allocate. If not default + size MHI_MAX_MTU will be used. + + +mhi channel node properties: + + +- reg + Usage: required + Value type: + Definition: physical channel number + +- label + Usage: required + Value type: + Definition: given name for the channel + +- mhi,num-elements + Usage: optional + Value type: + Definition: Number of elements transfer ring support + +- mhi,event-ring + Usage: required + Value type: + Definition: Event ring index associated with this channel + +- mhi,chan-dir + Usage: required + Value type: + Definition: Channel direction as defined by enum dma_data_direction + 0 = Bidirectional data transfer + 1 = UL data transfer + 2 = DL data transfer + 3 = No direction, not a regular data transfer channel + +- mhi,ee + Usage: required + Value type: + Definition: Channel execution enviornment as defined by enum MHI_EE + 1 = Bootloader stage + 2 = AMSS mode + +- mhi,pollcfg + Usage: optional + Value type: + Definition: MHI poll configuration, valid only when burst mode is enabled + 0 = Use default (device specific) polling configuration + For UL channels, value specifies the timer to poll MHI context in + milliseconds. + For DL channels, the threshold to poll the MHI context in multiple of + eight ring element. + +- mhi,data-type + Usage: required + Value type: + Definition: Data transfer type accepted as defined by enum MHI_XFER_TYPE + 0 = accept cpu address for buffer + 1 = accept skb + 2 = accept scatterlist + 3 = offload channel, does not accept any transfer type + +- mhi,doorbell-mode + Usage: required + Value type: + Definition: Channel doorbell mode configuration as defined by enum + MHI_BRSTMODE + 2 = burst mode disabled + 3 = burst
[PATCH v2 1/7] mhi_bus: core: initial checkin for modem host interface bus driver
This is the initial skeleton driver for mhi bus stack. MHI Host Interface is a communication protocol to be used by the host to control and communcate with modem over a high speed peripheral bus. This module will allow host to communicate with external devices that support MHI protocol. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- Documentation/00-INDEX| 2 + Documentation/devicetree/bindings/bus/mhi.txt | 258 Documentation/mhi.txt | 235 +++ drivers/bus/Kconfig | 8 + drivers/bus/Makefile | 1 + drivers/bus/mhi/Makefile | 6 + drivers/bus/mhi/core/Makefile | 1 + drivers/bus/mhi/core/mhi_init.c | 538 ++ drivers/bus/mhi/core/mhi_internal.h | 238 drivers/bus/mhi/core/mhi_main.c | 122 ++ include/linux/mhi.h | 341 include/linux/mod_devicetable.h | 12 + 12 files changed, 1762 insertions(+) create mode 100644 Documentation/devicetree/bindings/bus/mhi.txt create mode 100644 Documentation/mhi.txt create mode 100644 drivers/bus/mhi/Makefile create mode 100644 drivers/bus/mhi/core/Makefile create mode 100644 drivers/bus/mhi/core/mhi_init.c create mode 100644 drivers/bus/mhi/core/mhi_internal.h create mode 100644 drivers/bus/mhi/core/mhi_main.c create mode 100644 include/linux/mhi.h diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 708dc4c..44e2c6b 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -270,6 +270,8 @@ memory-hotplug.txt - Hotpluggable memory support, how to use and current status. men-chameleon-bus.txt - info on MEN chameleon bus. +mhi.txt + - Modem Host Interface mic/ - Intel Many Integrated Core (MIC) architecture device driver. mips/ diff --git a/Documentation/devicetree/bindings/bus/mhi.txt b/Documentation/devicetree/bindings/bus/mhi.txt new file mode 100644 index 000..19deb84 --- /dev/null +++ b/Documentation/devicetree/bindings/bus/mhi.txt @@ -0,0 +1,258 @@ +MHI Host Interface + +MHI used by the host to control and communicate with modem over +high speed peripheral bus. + +== +Node Structure +== + +Main node properties: + +- mhi,max-channels + Usage: required + Value type: + Definition: Maximum number of channels supported by this controller + +- mhi,timeout + Usage: optional + Value type: + Definition: Maximum timeout in ms wait for state and cmd completion + +- mhi,use-bb + Usage: optional + Value type: + Definition: Set true, if PCIe controller does not have full access to host + DDR, and we're using a dedicated memory pool like cma, or + carveout pool. Pool must support atomic allocation. + +- mhi,buffer-len + Usage: optional + Value type: + Definition: MHI automatically pre-allocate buffers for some channel. + Set the length of buffer size to allocate. If not default + size MHI_MAX_MTU will be used. + + +mhi channel node properties: + + +- reg + Usage: required + Value type: + Definition: physical channel number + +- label + Usage: required + Value type: + Definition: given name for the channel + +- mhi,num-elements + Usage: optional + Value type: + Definition: Number of elements transfer ring support + +- mhi,event-ring + Usage: required + Value type: + Definition: Event ring index associated with this channel + +- mhi,chan-dir + Usage: required + Value type: + Definition: Channel direction as defined by enum dma_data_direction + 0 = Bidirectional data transfer + 1 = UL data transfer + 2 = DL data transfer + 3 = No direction, not a regular data transfer channel + +- mhi,ee + Usage: required + Value type: + Definition: Channel execution enviornment as defined by enum MHI_EE + 1 = Bootloader stage + 2 = AMSS mode + +- mhi,pollcfg + Usage: optional + Value type: + Definition: MHI poll configuration, valid only when burst mode is enabled + 0 = Use default (device specific) polling configuration + For UL channels, value specifies the timer to poll MHI context in + milliseconds. + For DL channels, the threshold to poll the MHI context in multiple of + eight ring element. + +- mhi,data-type + Usage: required + Value type: + Definition: Data transfer type accepted as defined by enum MHI_XFER_TYPE + 0 = accept cpu address for buffer + 1 = accept skb + 2 = accept scatterlist + 3 = offload channel, does not accept any transfer type + +- mhi,doorbell-mode + Usage: required + Value type: + Definition: Channel doorbell mode configuration as defined by enum + MHI_BRSTMODE + 2 = burst mode disabled + 3 = burst
MHI code review
Hi Greg Kroah-Hartman\Arnd Bergmann and community Thank you for all the feedback, I believe I have addressed all the comments from previous patches. Also, I am excluding mhi network driver in this series. I still have some modifications to do. Please review the new patch series and share your feedback. Thanks again Sincerely, Sujeev
[PATCH v2 6/7] mhi_bus: controller: MHI support for QCOM modems
QCOM PCIe based modems uses MHI as the communication protocol. MHI control driver is the bus master for such modems. As the bus master driver, it oversees power management operations such as suspend, resume, powering on and off the device. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- Documentation/devicetree/bindings/bus/mhi_qcom.txt | 58 +++ arch/arm64/configs/defconfig | 1 + drivers/bus/Kconfig| 1 + drivers/bus/mhi/Makefile | 1 + drivers/bus/mhi/controllers/Kconfig| 13 + drivers/bus/mhi/controllers/Makefile | 1 + drivers/bus/mhi/controllers/mhi_qcom.c | 461 + drivers/bus/mhi/controllers/mhi_qcom.h | 67 +++ 8 files changed, 603 insertions(+) create mode 100644 Documentation/devicetree/bindings/bus/mhi_qcom.txt create mode 100644 drivers/bus/mhi/controllers/Kconfig create mode 100644 drivers/bus/mhi/controllers/Makefile create mode 100644 drivers/bus/mhi/controllers/mhi_qcom.c create mode 100644 drivers/bus/mhi/controllers/mhi_qcom.h diff --git a/Documentation/devicetree/bindings/bus/mhi_qcom.txt b/Documentation/devicetree/bindings/bus/mhi_qcom.txt new file mode 100644 index 000..0a48a50 --- /dev/null +++ b/Documentation/devicetree/bindings/bus/mhi_qcom.txt @@ -0,0 +1,58 @@ +Qualcomm Technologies Inc MHI Bus controller + +MHI control driver enables clients to communicate with external mode +using MHI protocol. + +== +Node Structure +== + +Main node properties: + +- reg + Usage: required + Value type: Array (5-cell PCI resource) of + Definition: First cell is devfn, which is determined by pci bus topology. + Assign the other cells 0 since they are not used. + +- qcom,smmu-cfg + Usage: required + Value type: + Definition: Required SMMU configuration bitmask for PCIe bus. + BIT mask: + BIT(0) : Attach address mapping to endpoint device + BIT(1) : Set attribute S1_BYPASS + BIT(2) : Set attribute FAST + BIT(3) : Set attribute ATOMIC + BIT(4) : Set attribute FORCE_COHERENT + +- qcom,addr-win + Usage: required if SMMU S1 translation is enabled + Value type: Array of + Definition: Pair of values describing iova start and stop address + +- MHI bus settings + Usage: required + Values: as defined by mhi.txt + Definition: Per definition of devicetree/bindings/bus/mhi.txt, define device + specific MHI configuration parameters. + + +Example: + + +/* pcie domain (root complex) modem connected to */ + { + /* pcie bus modem connected to */ + pci,bus@1 { + reg = <0 0 0 0 0>; + + qcom,mhi { + reg = <0 0 0 0 0>; + qcom,smmu-cfg = <0x3d>; + qcom,addr-win = <0x0 0x2000 0x0 0x3fff>; + + + }; + }; +}; diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 3562026..fd36426 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -168,6 +168,7 @@ CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_DMA_CMA=y CONFIG_MHI_BUS=y +CONFIG_MHI_QCOM=y CONFIG_MTD=y CONFIG_MTD_BLOCK=y CONFIG_MTD_M25P80=y diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 080d3c2..8c6827a 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -180,5 +180,6 @@ config MHI_BUS devices that support MHI protocol. source "drivers/bus/fsl-mc/Kconfig" +source drivers/bus/mhi/controllers/Kconfig endmenu diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile index f8f14f7..3458ba3 100644 --- a/drivers/bus/mhi/Makefile +++ b/drivers/bus/mhi/Makefile @@ -4,3 +4,4 @@ # core layer obj-y += core/ +obj-y += controllers/ \ No newline at end of file diff --git a/drivers/bus/mhi/controllers/Kconfig b/drivers/bus/mhi/controllers/Kconfig new file mode 100644 index 000..2586cc4 --- /dev/null +++ b/drivers/bus/mhi/controllers/Kconfig @@ -0,0 +1,13 @@ +menu "MHI controllers" + +config MHI_QCOM + tristate "MHI QCOM" + depends on MHI_BUS + help + If you say yes to this option, MHI bus support for QCOM modem chipsets + will be enabled. QCOM PCIe based modems uses MHI as the communication + protocol. MHI control driver is the bus master for such modems. As the + bus master driver, it oversees power management operations such as + suspend, resume, powering on and off the device. + +endmenu diff --git a/drivers/bus/mhi/controllers/Makefile b/drivers/bus/mhi/controllers/Makefile new file mode 100644 index 000..292f696 --- /dev/null +++ b/drivers/bus/mhi/controllers/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_MHI_QCOM) += mhi_qcom.o diff --git a/drivers/bus/mhi/controllers/mhi_qcom.c b/drive
MHI code review
Hi Greg Kroah-Hartman\Arnd Bergmann and community Thank you for all the feedback, I believe I have addressed all the comments from previous patches. Also, I am excluding mhi network driver in this series. I still have some modifications to do. Please review the new patch series and share your feedback. Thanks again Sincerely, Sujeev
[PATCH v2 6/7] mhi_bus: controller: MHI support for QCOM modems
QCOM PCIe based modems uses MHI as the communication protocol. MHI control driver is the bus master for such modems. As the bus master driver, it oversees power management operations such as suspend, resume, powering on and off the device. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- Documentation/devicetree/bindings/bus/mhi_qcom.txt | 58 +++ arch/arm64/configs/defconfig | 1 + drivers/bus/Kconfig| 1 + drivers/bus/mhi/Makefile | 1 + drivers/bus/mhi/controllers/Kconfig| 13 + drivers/bus/mhi/controllers/Makefile | 1 + drivers/bus/mhi/controllers/mhi_qcom.c | 461 + drivers/bus/mhi/controllers/mhi_qcom.h | 67 +++ 8 files changed, 603 insertions(+) create mode 100644 Documentation/devicetree/bindings/bus/mhi_qcom.txt create mode 100644 drivers/bus/mhi/controllers/Kconfig create mode 100644 drivers/bus/mhi/controllers/Makefile create mode 100644 drivers/bus/mhi/controllers/mhi_qcom.c create mode 100644 drivers/bus/mhi/controllers/mhi_qcom.h diff --git a/Documentation/devicetree/bindings/bus/mhi_qcom.txt b/Documentation/devicetree/bindings/bus/mhi_qcom.txt new file mode 100644 index 000..0a48a50 --- /dev/null +++ b/Documentation/devicetree/bindings/bus/mhi_qcom.txt @@ -0,0 +1,58 @@ +Qualcomm Technologies Inc MHI Bus controller + +MHI control driver enables clients to communicate with external mode +using MHI protocol. + +== +Node Structure +== + +Main node properties: + +- reg + Usage: required + Value type: Array (5-cell PCI resource) of + Definition: First cell is devfn, which is determined by pci bus topology. + Assign the other cells 0 since they are not used. + +- qcom,smmu-cfg + Usage: required + Value type: + Definition: Required SMMU configuration bitmask for PCIe bus. + BIT mask: + BIT(0) : Attach address mapping to endpoint device + BIT(1) : Set attribute S1_BYPASS + BIT(2) : Set attribute FAST + BIT(3) : Set attribute ATOMIC + BIT(4) : Set attribute FORCE_COHERENT + +- qcom,addr-win + Usage: required if SMMU S1 translation is enabled + Value type: Array of + Definition: Pair of values describing iova start and stop address + +- MHI bus settings + Usage: required + Values: as defined by mhi.txt + Definition: Per definition of devicetree/bindings/bus/mhi.txt, define device + specific MHI configuration parameters. + + +Example: + + +/* pcie domain (root complex) modem connected to */ + { + /* pcie bus modem connected to */ + pci,bus@1 { + reg = <0 0 0 0 0>; + + qcom,mhi { + reg = <0 0 0 0 0>; + qcom,smmu-cfg = <0x3d>; + qcom,addr-win = <0x0 0x2000 0x0 0x3fff>; + + + }; + }; +}; diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 3562026..fd36426 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -168,6 +168,7 @@ CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_DMA_CMA=y CONFIG_MHI_BUS=y +CONFIG_MHI_QCOM=y CONFIG_MTD=y CONFIG_MTD_BLOCK=y CONFIG_MTD_M25P80=y diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 080d3c2..8c6827a 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -180,5 +180,6 @@ config MHI_BUS devices that support MHI protocol. source "drivers/bus/fsl-mc/Kconfig" +source drivers/bus/mhi/controllers/Kconfig endmenu diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile index f8f14f7..3458ba3 100644 --- a/drivers/bus/mhi/Makefile +++ b/drivers/bus/mhi/Makefile @@ -4,3 +4,4 @@ # core layer obj-y += core/ +obj-y += controllers/ \ No newline at end of file diff --git a/drivers/bus/mhi/controllers/Kconfig b/drivers/bus/mhi/controllers/Kconfig new file mode 100644 index 000..2586cc4 --- /dev/null +++ b/drivers/bus/mhi/controllers/Kconfig @@ -0,0 +1,13 @@ +menu "MHI controllers" + +config MHI_QCOM + tristate "MHI QCOM" + depends on MHI_BUS + help + If you say yes to this option, MHI bus support for QCOM modem chipsets + will be enabled. QCOM PCIe based modems uses MHI as the communication + protocol. MHI control driver is the bus master for such modems. As the + bus master driver, it oversees power management operations such as + suspend, resume, powering on and off the device. + +endmenu diff --git a/drivers/bus/mhi/controllers/Makefile b/drivers/bus/mhi/controllers/Makefile new file mode 100644 index 000..292f696 --- /dev/null +++ b/drivers/bus/mhi/controllers/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_MHI_QCOM) += mhi_qcom.o diff --git a/drivers/bus/mhi/controllers/mhi_qcom.c b/drive
[PATCH v2 7/7] mhi_bus: dev: uci: add user space interface driver
This module allows user space clients to transfer data between external modem and host using standard file operations. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- arch/arm64/configs/defconfig | 1 + drivers/bus/Kconfig | 1 + drivers/bus/mhi/Makefile | 3 +- drivers/bus/mhi/devices/Kconfig | 13 + drivers/bus/mhi/devices/Makefile | 1 + drivers/bus/mhi/devices/mhi_uci.c | 590 ++ 6 files changed, 608 insertions(+), 1 deletion(-) create mode 100644 drivers/bus/mhi/devices/Kconfig create mode 100644 drivers/bus/mhi/devices/Makefile create mode 100644 drivers/bus/mhi/devices/mhi_uci.c diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index fd36426..7f68d706 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -169,6 +169,7 @@ CONFIG_DEVTMPFS_MOUNT=y CONFIG_DMA_CMA=y CONFIG_MHI_BUS=y CONFIG_MHI_QCOM=y +CONFIG_MHI_UCI=y CONFIG_MTD=y CONFIG_MTD_BLOCK=y CONFIG_MTD_M25P80=y diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 8c6827a..cb10366 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -181,5 +181,6 @@ config MHI_BUS source "drivers/bus/fsl-mc/Kconfig" source drivers/bus/mhi/controllers/Kconfig +source drivers/bus/mhi/devices/Kconfig endmenu diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile index 3458ba3..2382e04 100644 --- a/drivers/bus/mhi/Makefile +++ b/drivers/bus/mhi/Makefile @@ -4,4 +4,5 @@ # core layer obj-y += core/ -obj-y += controllers/ \ No newline at end of file +obj-y += controllers/ +obj-y += devices/ diff --git a/drivers/bus/mhi/devices/Kconfig b/drivers/bus/mhi/devices/Kconfig new file mode 100644 index 000..45cd742 --- /dev/null +++ b/drivers/bus/mhi/devices/Kconfig @@ -0,0 +1,13 @@ +menu "MHI device support" + +config MHI_UCI + tristate "MHI UCI" + depends on MHI_BUS + help + MHI based uci driver is for transferring data between host and + modem using standard file operations from user space. Open, read, + write, ioctl, and close operations are supported by this driver. + Please check mhi_uci_match_table for all supported channels that + are exposed to userspace. + +endmenu diff --git a/drivers/bus/mhi/devices/Makefile b/drivers/bus/mhi/devices/Makefile new file mode 100644 index 000..ddc0613 --- /dev/null +++ b/drivers/bus/mhi/devices/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_MHI_UCI) +=mhi_uci.o diff --git a/drivers/bus/mhi/devices/mhi_uci.c b/drivers/bus/mhi/devices/mhi_uci.c new file mode 100644 index 000..ad60a15 --- /dev/null +++ b/drivers/bus/mhi/devices/mhi_uci.c @@ -0,0 +1,590 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_NAME "mhi" +#define MHI_UCI_DRIVER_NAME "mhi_uci" + +struct uci_chan { + wait_queue_head_t wq; + spinlock_t lock; + struct list_head pending; /* user space waiting to read */ + struct uci_buf *cur_buf; /* current buffer user space reading */ + size_t rx_size; +}; + +struct uci_buf { + void *data; + size_t len; + struct list_head node; +}; + +struct uci_dev { + struct list_head node; + dev_t devt; + struct device *dev; + struct mhi_device *mhi_dev; + const char *chan; + struct mutex mutex; /* sync open and close */ + struct uci_chan ul_chan; + struct uci_chan dl_chan; + size_t mtu; + int ref_count; + bool enabled; +}; + +struct mhi_uci_drv { + struct list_head head; + struct mutex lock; + struct class *class; + int major; + dev_t dev_t; +}; + +#define MAX_UCI_DEVICES (64) + +static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES); +static struct mhi_uci_drv mhi_uci_drv; + +static int mhi_queue_inbound(struct uci_dev *uci_dev) +{ + struct mhi_device *mhi_dev = uci_dev->mhi_dev; + int nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); + size_t mtu = uci_dev->mtu; + void *buf; + struct uci_buf *uci_buf; + int ret = -EIO, i; + + for (i = 0; i < nr_trbs; i++) { + buf = kmalloc(mtu + sizeof(*uci_buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + uci_buf = buf + mtu; + uci_buf->data = buf; + + ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf, mtu, +MHI_EOT); + if (ret) { + kfree(buf); + return ret; + } + } + + return ret; +} + +static long mhi_uci_ioctl
[PATCH v2 5/7] mhi_bus: core: add support to get external modem time
For accurate synchronizations between external modem and host processor, mhi host will capture modem time relative to host time. Client may use time measurements for adjusting any drift between host and modem. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- Documentation/devicetree/bindings/bus/mhi.txt | 7 + Documentation/mhi.txt | 41 drivers/bus/mhi/core/mhi_init.c | 111 +++ drivers/bus/mhi/core/mhi_internal.h | 57 +- drivers/bus/mhi/core/mhi_main.c | 263 +- drivers/bus/mhi/core/mhi_pm.c | 7 + include/linux/mhi.h | 7 + 7 files changed, 486 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/bus/mhi.txt b/Documentation/devicetree/bindings/bus/mhi.txt index 19deb84..1012ff2 100644 --- a/Documentation/devicetree/bindings/bus/mhi.txt +++ b/Documentation/devicetree/bindings/bus/mhi.txt @@ -19,6 +19,13 @@ Main node properties: Value type: Definition: Maximum timeout in ms wait for state and cmd completion +- mhi,time-sync + Usage: optional + Value type: + Definition: Set true, if the external device support MHI get time + feature for time synchronization between host processor and + external modem. + - mhi,use-bb Usage: optional Value type: diff --git a/Documentation/mhi.txt b/Documentation/mhi.txt index 1c501f1..9287899 100644 --- a/Documentation/mhi.txt +++ b/Documentation/mhi.txt @@ -137,6 +137,47 @@ Example Operation for data transfer: 8. Host wakes up and check event ring for completion event 9. Host update the Event[i].ctxt.WP to indicate processed of completion event. +Time sync +- +To synchronize two applications between host and external modem, MHI provide +native support to get external modems free running timer value in a fast +reliable method. MHI clients do not need to create client specific methods to +get modem time. + +When client requests modem time, MHI host will automatically capture host time +at that moment so clients are able to do accurate drift adjustment. + +Example: + +Client request time @ time T1 + +Host Time: Tx +Modem Time: Ty + +Client request time @ time T2 +Host Time: Txx +Modem Time: Tyy + +Then drift is: +Tyy - Ty + == Txx - Tx + +Clients are free to implement their own drift algorithms, what MHI host provide +is a way to accurately correlate host time with external modem time. + +To avoid link level latencies, controller must support capabilities to disable +any link level latency. + +During Time capture host will: + 1. Capture host time + 2. Trigger doorbell to capture modem time + +It's important time between Step 2 to Step 1 is deterministic as possible. +Therefore, MHI host will: + 1. Disable any MHI related to low power modes. + 2. Disable preemption + 3. Request bus master to disable any link level latencies. Controller + should disable all low power modes such as L0s, L1, L1ss. + MHI States -- diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index b09767a..e1e1b8c 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -362,6 +362,69 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl) return ret; } +int mhi_init_timesync(struct mhi_controller *mhi_cntrl) +{ + struct mhi_timesync *mhi_tsync = mhi_cntrl->mhi_tsync; + u32 time_offset, db_offset; + int ret; + + reinit_completion(_tsync->completion); + read_lock_bh(_cntrl->pm_lock); + if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { + read_unlock_bh(_cntrl->pm_lock); + return -EIO; + } + + mhi_cntrl->wake_get(mhi_cntrl, false); + read_unlock_bh(_cntrl->pm_lock); + mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); + mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); + + ret = mhi_send_cmd(mhi_cntrl, NULL, MHI_CMD_TIMSYNC_CFG); + if (ret) + goto error_send_cmd; + + ret = wait_for_completion_timeout(_tsync->completion, + msecs_to_jiffies(mhi_cntrl->timeout_ms)); + + if (!ret || mhi_tsync->ccs != MHI_EV_CC_SUCCESS) { + ret = -EIO; + goto error_send_cmd; + } + + read_lock_bh(_cntrl->pm_lock); + mhi_cntrl->wake_put(mhi_cntrl, false); + + ret = -EIO; + + if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) + goto error_sync_cap; + + ret = mhi_get_capability_offset(mhi_cntrl, TIMESYNC_CAP_ID, + _offset); + if (ret) + goto error_sync_cap; + + ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, + time_offset + TIMESYNC_DB_OFFSET, _offset)
[PATCH v2 7/7] mhi_bus: dev: uci: add user space interface driver
This module allows user space clients to transfer data between external modem and host using standard file operations. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- arch/arm64/configs/defconfig | 1 + drivers/bus/Kconfig | 1 + drivers/bus/mhi/Makefile | 3 +- drivers/bus/mhi/devices/Kconfig | 13 + drivers/bus/mhi/devices/Makefile | 1 + drivers/bus/mhi/devices/mhi_uci.c | 590 ++ 6 files changed, 608 insertions(+), 1 deletion(-) create mode 100644 drivers/bus/mhi/devices/Kconfig create mode 100644 drivers/bus/mhi/devices/Makefile create mode 100644 drivers/bus/mhi/devices/mhi_uci.c diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index fd36426..7f68d706 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -169,6 +169,7 @@ CONFIG_DEVTMPFS_MOUNT=y CONFIG_DMA_CMA=y CONFIG_MHI_BUS=y CONFIG_MHI_QCOM=y +CONFIG_MHI_UCI=y CONFIG_MTD=y CONFIG_MTD_BLOCK=y CONFIG_MTD_M25P80=y diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 8c6827a..cb10366 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -181,5 +181,6 @@ config MHI_BUS source "drivers/bus/fsl-mc/Kconfig" source drivers/bus/mhi/controllers/Kconfig +source drivers/bus/mhi/devices/Kconfig endmenu diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile index 3458ba3..2382e04 100644 --- a/drivers/bus/mhi/Makefile +++ b/drivers/bus/mhi/Makefile @@ -4,4 +4,5 @@ # core layer obj-y += core/ -obj-y += controllers/ \ No newline at end of file +obj-y += controllers/ +obj-y += devices/ diff --git a/drivers/bus/mhi/devices/Kconfig b/drivers/bus/mhi/devices/Kconfig new file mode 100644 index 000..45cd742 --- /dev/null +++ b/drivers/bus/mhi/devices/Kconfig @@ -0,0 +1,13 @@ +menu "MHI device support" + +config MHI_UCI + tristate "MHI UCI" + depends on MHI_BUS + help + MHI based uci driver is for transferring data between host and + modem using standard file operations from user space. Open, read, + write, ioctl, and close operations are supported by this driver. + Please check mhi_uci_match_table for all supported channels that + are exposed to userspace. + +endmenu diff --git a/drivers/bus/mhi/devices/Makefile b/drivers/bus/mhi/devices/Makefile new file mode 100644 index 000..ddc0613 --- /dev/null +++ b/drivers/bus/mhi/devices/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_MHI_UCI) +=mhi_uci.o diff --git a/drivers/bus/mhi/devices/mhi_uci.c b/drivers/bus/mhi/devices/mhi_uci.c new file mode 100644 index 000..ad60a15 --- /dev/null +++ b/drivers/bus/mhi/devices/mhi_uci.c @@ -0,0 +1,590 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_NAME "mhi" +#define MHI_UCI_DRIVER_NAME "mhi_uci" + +struct uci_chan { + wait_queue_head_t wq; + spinlock_t lock; + struct list_head pending; /* user space waiting to read */ + struct uci_buf *cur_buf; /* current buffer user space reading */ + size_t rx_size; +}; + +struct uci_buf { + void *data; + size_t len; + struct list_head node; +}; + +struct uci_dev { + struct list_head node; + dev_t devt; + struct device *dev; + struct mhi_device *mhi_dev; + const char *chan; + struct mutex mutex; /* sync open and close */ + struct uci_chan ul_chan; + struct uci_chan dl_chan; + size_t mtu; + int ref_count; + bool enabled; +}; + +struct mhi_uci_drv { + struct list_head head; + struct mutex lock; + struct class *class; + int major; + dev_t dev_t; +}; + +#define MAX_UCI_DEVICES (64) + +static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES); +static struct mhi_uci_drv mhi_uci_drv; + +static int mhi_queue_inbound(struct uci_dev *uci_dev) +{ + struct mhi_device *mhi_dev = uci_dev->mhi_dev; + int nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); + size_t mtu = uci_dev->mtu; + void *buf; + struct uci_buf *uci_buf; + int ret = -EIO, i; + + for (i = 0; i < nr_trbs; i++) { + buf = kmalloc(mtu + sizeof(*uci_buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + uci_buf = buf + mtu; + uci_buf->data = buf; + + ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf, mtu, +MHI_EOT); + if (ret) { + kfree(buf); + return ret; + } + } + + return ret; +} + +static long mhi_uci_ioctl
[PATCH v2 5/7] mhi_bus: core: add support to get external modem time
For accurate synchronizations between external modem and host processor, mhi host will capture modem time relative to host time. Client may use time measurements for adjusting any drift between host and modem. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- Documentation/devicetree/bindings/bus/mhi.txt | 7 + Documentation/mhi.txt | 41 drivers/bus/mhi/core/mhi_init.c | 111 +++ drivers/bus/mhi/core/mhi_internal.h | 57 +- drivers/bus/mhi/core/mhi_main.c | 263 +- drivers/bus/mhi/core/mhi_pm.c | 7 + include/linux/mhi.h | 7 + 7 files changed, 486 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/bus/mhi.txt b/Documentation/devicetree/bindings/bus/mhi.txt index 19deb84..1012ff2 100644 --- a/Documentation/devicetree/bindings/bus/mhi.txt +++ b/Documentation/devicetree/bindings/bus/mhi.txt @@ -19,6 +19,13 @@ Main node properties: Value type: Definition: Maximum timeout in ms wait for state and cmd completion +- mhi,time-sync + Usage: optional + Value type: + Definition: Set true, if the external device support MHI get time + feature for time synchronization between host processor and + external modem. + - mhi,use-bb Usage: optional Value type: diff --git a/Documentation/mhi.txt b/Documentation/mhi.txt index 1c501f1..9287899 100644 --- a/Documentation/mhi.txt +++ b/Documentation/mhi.txt @@ -137,6 +137,47 @@ Example Operation for data transfer: 8. Host wakes up and check event ring for completion event 9. Host update the Event[i].ctxt.WP to indicate processed of completion event. +Time sync +- +To synchronize two applications between host and external modem, MHI provide +native support to get external modems free running timer value in a fast +reliable method. MHI clients do not need to create client specific methods to +get modem time. + +When client requests modem time, MHI host will automatically capture host time +at that moment so clients are able to do accurate drift adjustment. + +Example: + +Client request time @ time T1 + +Host Time: Tx +Modem Time: Ty + +Client request time @ time T2 +Host Time: Txx +Modem Time: Tyy + +Then drift is: +Tyy - Ty + == Txx - Tx + +Clients are free to implement their own drift algorithms, what MHI host provide +is a way to accurately correlate host time with external modem time. + +To avoid link level latencies, controller must support capabilities to disable +any link level latency. + +During Time capture host will: + 1. Capture host time + 2. Trigger doorbell to capture modem time + +It's important time between Step 2 to Step 1 is deterministic as possible. +Therefore, MHI host will: + 1. Disable any MHI related to low power modes. + 2. Disable preemption + 3. Request bus master to disable any link level latencies. Controller + should disable all low power modes such as L0s, L1, L1ss. + MHI States -- diff --git a/drivers/bus/mhi/core/mhi_init.c b/drivers/bus/mhi/core/mhi_init.c index b09767a..e1e1b8c 100644 --- a/drivers/bus/mhi/core/mhi_init.c +++ b/drivers/bus/mhi/core/mhi_init.c @@ -362,6 +362,69 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl) return ret; } +int mhi_init_timesync(struct mhi_controller *mhi_cntrl) +{ + struct mhi_timesync *mhi_tsync = mhi_cntrl->mhi_tsync; + u32 time_offset, db_offset; + int ret; + + reinit_completion(_tsync->completion); + read_lock_bh(_cntrl->pm_lock); + if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { + read_unlock_bh(_cntrl->pm_lock); + return -EIO; + } + + mhi_cntrl->wake_get(mhi_cntrl, false); + read_unlock_bh(_cntrl->pm_lock); + mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); + mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); + + ret = mhi_send_cmd(mhi_cntrl, NULL, MHI_CMD_TIMSYNC_CFG); + if (ret) + goto error_send_cmd; + + ret = wait_for_completion_timeout(_tsync->completion, + msecs_to_jiffies(mhi_cntrl->timeout_ms)); + + if (!ret || mhi_tsync->ccs != MHI_EV_CC_SUCCESS) { + ret = -EIO; + goto error_send_cmd; + } + + read_lock_bh(_cntrl->pm_lock); + mhi_cntrl->wake_put(mhi_cntrl, false); + + ret = -EIO; + + if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) + goto error_sync_cap; + + ret = mhi_get_capability_offset(mhi_cntrl, TIMESYNC_CAP_ID, + _offset); + if (ret) + goto error_sync_cap; + + ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, + time_offset + TIMESYNC_DB_OFFSET, _offset)
[PATCH v2 4/7] mhi_bus: core: add support for handling ioctl cmds
User space clients use RS232 control signaling mechanism to communicate call status between host and modem. Adding support to handle ioctl commands from user space. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- drivers/bus/mhi/core/Makefile | 2 +- drivers/bus/mhi/core/mhi_dtr.c | 218 drivers/bus/mhi/core/mhi_init.c | 8 +- 3 files changed, 226 insertions(+), 2 deletions(-) create mode 100644 drivers/bus/mhi/core/mhi_dtr.c diff --git a/drivers/bus/mhi/core/Makefile b/drivers/bus/mhi/core/Makefile index a6015ab..a743fbf 100644 --- a/drivers/bus/mhi/core/Makefile +++ b/drivers/bus/mhi/core/Makefile @@ -1 +1 @@ -obj-$(CONFIG_MHI_BUS) +=mhi_init.o mhi_main.o mhi_pm.o mhi_boot.o +obj-$(CONFIG_MHI_BUS) +=mhi_init.o mhi_main.o mhi_pm.o mhi_boot.o mhi_dtr.o diff --git a/drivers/bus/mhi/core/mhi_dtr.c b/drivers/bus/mhi/core/mhi_dtr.c new file mode 100644 index 000..5c2409b --- /dev/null +++ b/drivers/bus/mhi/core/mhi_dtr.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mhi_internal.h" + +struct __packed dtr_ctrl_msg { + u32 preamble; + u32 msg_id; + u32 dest_id; + u32 size; + u32 msg; +}; + +#define CTRL_MAGIC (0x4C525443) +#define CTRL_MSG_DTR BIT(0) +#define CTRL_MSG_RTS BIT(1) +#define CTRL_MSG_DCD BIT(0) +#define CTRL_MSG_DSR BIT(1) +#define CTRL_MSG_RI BIT(3) +#define CTRL_HOST_STATE (0x10) +#define CTRL_DEVICE_STATE (0x11) +#define CTRL_GET_CHID(dtr) (dtr->dest_id & 0xFF) + +static int mhi_dtr_tiocmset(struct mhi_controller *mhi_cntrl, + struct mhi_device *mhi_dev, + u32 tiocm) +{ + struct dtr_ctrl_msg *dtr_msg = NULL; + struct mhi_chan *dtr_chan = mhi_cntrl->dtr_dev->ul_chan; + spinlock_t *res_lock = _dev->dev.devres_lock; + u32 cur_tiocm; + int ret = 0; + + cur_tiocm = mhi_dev->tiocm & ~(TIOCM_CD | TIOCM_DSR | TIOCM_RI); + + tiocm &= (TIOCM_DTR | TIOCM_RTS); + + /* state did not changed */ + if (cur_tiocm == tiocm) + return 0; + + mutex_lock(_chan->mutex); + + dtr_msg = kzalloc(sizeof(*dtr_msg), GFP_KERNEL); + if (!dtr_msg) { + ret = -ENOMEM; + goto tiocm_exit; + } + + dtr_msg->preamble = CTRL_MAGIC; + dtr_msg->msg_id = CTRL_HOST_STATE; + dtr_msg->dest_id = mhi_dev->ul_chan_id; + dtr_msg->size = sizeof(u32); + if (tiocm & TIOCM_DTR) + dtr_msg->msg |= CTRL_MSG_DTR; + if (tiocm & TIOCM_RTS) + dtr_msg->msg |= CTRL_MSG_RTS; + + reinit_completion(_chan->completion); + ret = mhi_queue_transfer(mhi_cntrl->dtr_dev, DMA_TO_DEVICE, dtr_msg, +sizeof(*dtr_msg), MHI_EOT); + if (ret) + goto tiocm_exit; + + ret = wait_for_completion_timeout(_chan->completion, + msecs_to_jiffies(mhi_cntrl->timeout_ms)); + if (!ret) { + dev_err(mhi_cntrl->dev, "Failed to recv transfer callback\n"); + ret = -EIO; + goto tiocm_exit; + } + + ret = 0; + spin_lock_irq(res_lock); + mhi_dev->tiocm &= ~(TIOCM_DTR | TIOCM_RTS); + mhi_dev->tiocm |= tiocm; + spin_unlock_irq(res_lock); + +tiocm_exit: + kfree(dtr_msg); + mutex_unlock(_chan->mutex); + + return ret; +} + +long mhi_ioctl(struct mhi_device *mhi_dev, unsigned int cmd, unsigned long arg) +{ + struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; + int ret; + + /* ioctl not supported by this controller */ + if (!mhi_cntrl->dtr_dev) + return -EIO; + + switch (cmd) { + case TIOCMGET: + return mhi_dev->tiocm; + case TIOCMSET: + { + u32 tiocm; + + ret = get_user(tiocm, (u32 *)arg); + if (ret) + return ret; + + return mhi_dtr_tiocmset(mhi_cntrl, mhi_dev, tiocm); + } + default: + break; + } + + return -EINVAL; +} +EXPORT_SYMBOL(mhi_ioctl); + +static void mhi_dtr_dl_xfer_cb(struct mhi_device *mhi_dev, + struct mhi_result *mhi_result) +{ + struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; + struct dtr_ctrl_msg *dtr_msg = mhi_result->buf_addr; + u32 chan; + spinlock_t *res_lock; + + if (mhi_result->bytes_xferd != sizeof(*dtr_msg)) { + dev_err(mhi_cntrl->dev, "Unexpected length %zu received\n", +
[PATCH v2 4/7] mhi_bus: core: add support for handling ioctl cmds
User space clients use RS232 control signaling mechanism to communicate call status between host and modem. Adding support to handle ioctl commands from user space. Signed-off-by: Sujeev Dias Reviewed-by: Tony Truong Signed-off-by: Siddartha Mohanadoss --- drivers/bus/mhi/core/Makefile | 2 +- drivers/bus/mhi/core/mhi_dtr.c | 218 drivers/bus/mhi/core/mhi_init.c | 8 +- 3 files changed, 226 insertions(+), 2 deletions(-) create mode 100644 drivers/bus/mhi/core/mhi_dtr.c diff --git a/drivers/bus/mhi/core/Makefile b/drivers/bus/mhi/core/Makefile index a6015ab..a743fbf 100644 --- a/drivers/bus/mhi/core/Makefile +++ b/drivers/bus/mhi/core/Makefile @@ -1 +1 @@ -obj-$(CONFIG_MHI_BUS) +=mhi_init.o mhi_main.o mhi_pm.o mhi_boot.o +obj-$(CONFIG_MHI_BUS) +=mhi_init.o mhi_main.o mhi_pm.o mhi_boot.o mhi_dtr.o diff --git a/drivers/bus/mhi/core/mhi_dtr.c b/drivers/bus/mhi/core/mhi_dtr.c new file mode 100644 index 000..5c2409b --- /dev/null +++ b/drivers/bus/mhi/core/mhi_dtr.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mhi_internal.h" + +struct __packed dtr_ctrl_msg { + u32 preamble; + u32 msg_id; + u32 dest_id; + u32 size; + u32 msg; +}; + +#define CTRL_MAGIC (0x4C525443) +#define CTRL_MSG_DTR BIT(0) +#define CTRL_MSG_RTS BIT(1) +#define CTRL_MSG_DCD BIT(0) +#define CTRL_MSG_DSR BIT(1) +#define CTRL_MSG_RI BIT(3) +#define CTRL_HOST_STATE (0x10) +#define CTRL_DEVICE_STATE (0x11) +#define CTRL_GET_CHID(dtr) (dtr->dest_id & 0xFF) + +static int mhi_dtr_tiocmset(struct mhi_controller *mhi_cntrl, + struct mhi_device *mhi_dev, + u32 tiocm) +{ + struct dtr_ctrl_msg *dtr_msg = NULL; + struct mhi_chan *dtr_chan = mhi_cntrl->dtr_dev->ul_chan; + spinlock_t *res_lock = _dev->dev.devres_lock; + u32 cur_tiocm; + int ret = 0; + + cur_tiocm = mhi_dev->tiocm & ~(TIOCM_CD | TIOCM_DSR | TIOCM_RI); + + tiocm &= (TIOCM_DTR | TIOCM_RTS); + + /* state did not changed */ + if (cur_tiocm == tiocm) + return 0; + + mutex_lock(_chan->mutex); + + dtr_msg = kzalloc(sizeof(*dtr_msg), GFP_KERNEL); + if (!dtr_msg) { + ret = -ENOMEM; + goto tiocm_exit; + } + + dtr_msg->preamble = CTRL_MAGIC; + dtr_msg->msg_id = CTRL_HOST_STATE; + dtr_msg->dest_id = mhi_dev->ul_chan_id; + dtr_msg->size = sizeof(u32); + if (tiocm & TIOCM_DTR) + dtr_msg->msg |= CTRL_MSG_DTR; + if (tiocm & TIOCM_RTS) + dtr_msg->msg |= CTRL_MSG_RTS; + + reinit_completion(_chan->completion); + ret = mhi_queue_transfer(mhi_cntrl->dtr_dev, DMA_TO_DEVICE, dtr_msg, +sizeof(*dtr_msg), MHI_EOT); + if (ret) + goto tiocm_exit; + + ret = wait_for_completion_timeout(_chan->completion, + msecs_to_jiffies(mhi_cntrl->timeout_ms)); + if (!ret) { + dev_err(mhi_cntrl->dev, "Failed to recv transfer callback\n"); + ret = -EIO; + goto tiocm_exit; + } + + ret = 0; + spin_lock_irq(res_lock); + mhi_dev->tiocm &= ~(TIOCM_DTR | TIOCM_RTS); + mhi_dev->tiocm |= tiocm; + spin_unlock_irq(res_lock); + +tiocm_exit: + kfree(dtr_msg); + mutex_unlock(_chan->mutex); + + return ret; +} + +long mhi_ioctl(struct mhi_device *mhi_dev, unsigned int cmd, unsigned long arg) +{ + struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; + int ret; + + /* ioctl not supported by this controller */ + if (!mhi_cntrl->dtr_dev) + return -EIO; + + switch (cmd) { + case TIOCMGET: + return mhi_dev->tiocm; + case TIOCMSET: + { + u32 tiocm; + + ret = get_user(tiocm, (u32 *)arg); + if (ret) + return ret; + + return mhi_dtr_tiocmset(mhi_cntrl, mhi_dev, tiocm); + } + default: + break; + } + + return -EINVAL; +} +EXPORT_SYMBOL(mhi_ioctl); + +static void mhi_dtr_dl_xfer_cb(struct mhi_device *mhi_dev, + struct mhi_result *mhi_result) +{ + struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; + struct dtr_ctrl_msg *dtr_msg = mhi_result->buf_addr; + u32 chan; + spinlock_t *res_lock; + + if (mhi_result->bytes_xferd != sizeof(*dtr_msg)) { + dev_err(mhi_cntrl->dev, "Unexpected length %zu received\n", +
Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface
Hi Pavel On 05/03/2018 12:21 PM, Pavel Machek wrote: Hi! MHI Host Interface is a communication protocol to be used by the host to control and communcate with modem over a high speed peripheral bus. This module will allow host to communicate with external devices that support MHI protocol. I have Motorola Droid 4 cellphone here, with Qualcomm GSM modem. But it talks over serial line and USB. I guess MHI is not applicable to my hardware? MHI is for PCIe based modem, in any case I can't comment about commercial devices. +MHI Devices +--- +Logical device that bind to maximum of two physical MHI channels. Once MHI is in +powered on state, each supported channel by controller will be allocated as a +mhi_device. What kind of protocol is running over MHI? I guess its not AT commands. QMI? Or something entirely different? All modem services between external modem and host go over MHI. So QMI, AT, all other data and control services go thru MHI host driver. Pavel Thanks Sujeev -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface
Hi Pavel On 05/03/2018 12:21 PM, Pavel Machek wrote: Hi! MHI Host Interface is a communication protocol to be used by the host to control and communcate with modem over a high speed peripheral bus. This module will allow host to communicate with external devices that support MHI protocol. I have Motorola Droid 4 cellphone here, with Qualcomm GSM modem. But it talks over serial line and USB. I guess MHI is not applicable to my hardware? MHI is for PCIe based modem, in any case I can't comment about commercial devices. +MHI Devices +--- +Logical device that bind to maximum of two physical MHI channels. Once MHI is in +powered on state, each supported channel by controller will be allocated as a +mhi_device. What kind of protocol is running over MHI? I guess its not AT commands. QMI? Or something entirely different? All modem services between external modem and host go over MHI. So QMI, AT, all other data and control services go thru MHI host driver. Pavel Thanks Sujeev -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface
On 04/27/2018 05:18 AM, Arnd Bergmann wrote: On Fri, Apr 27, 2018 at 4:23 AM, Sujeev Dias <sd...@codeaurora.org> wrote: diff --git a/Documentation/devicetree/bindings/bus/mhi.txt b/Documentation/devicetree/bindings/bus/mhi.txt new file mode 100644 index 000..ea1b620 --- /dev/null +++ b/Documentation/devicetree/bindings/bus/mhi.txt @@ -0,0 +1,141 @@ +MHI Host Interface + +MHI used by the host to control and communicate with modem over +high speed peripheral bus. + +== +Node Structure +== + +Main node properties: + +- mhi,max-channels + Usage: required + Value type: + Definition: Maximum number of channels supported by this controller + +- mhi,chan-cfg + Usage: required + Value type: Array of + Definition: Array of tuples describe channel configuration. + 1st element: Physical channel number + 2nd element: Transfer ring length in elements + 3rd element: Event ring associated with this channel + 4th element: Channel direction as defined by enum dma_data_direction + 1 = UL data transfer + 2 = DL data transfer + 5th element: Channel doorbell mode configuration as defined by + enum MHI_BRSTMODE + 2 = burst mode disabled + 3 = burst mode enabled + 6th element: mhi doorbell configuration, valid only when burst mode + enabled. + 0 = Use default (device specific) polling configuration + For UL channels, value specifies the timer to poll MHI context + in milliseconds. + For DL channels, the threshold to poll the MHI context + in multiple of eight ring element. + 7th element: Channel execution enviornment as defined by enum MHI_EE + 1 = Bootloader stage + 2 = AMSS mode + 8th element: data transfer type accepted as defined by enum + MHI_XFER_TYPE + 0 = accept cpu address for buffer + 1 = accept skb + 2 = accept scatterlist + 3 = offload channel, does not accept any transfer type + 9th element: Bitwise configuration settings for the channel + Bit mask: + BIT(0) : LPM notify, this channel master requre lpm enter/exit + notifications. + BIT(1) : Offload channel, MHI host only involved in setting up + the data pipe. Not involved in active data transfer. + BIT(2) : Must switch to doorbell mode whenever MHI M0 state + transition happens. + BIT(3) : MHI bus driver pre-allocate buffer for this channel. + If set, clients not allowed to queue buffers. Valid only for DL + direction. + +- mhi,chan-names + Usage: required + Value type: Array of + Definition: Channel names configured in mhi,chan-cfg. I think the top-level structure would be better done by requiring a child for each channel and moving the mhi,chan-cfg into the children nodes, either as separate properties, or some of the fields combined into a 'reg' property. +- mhi,fw-name + Usage: optional + Value type: + Definition: Firmware image name to upload The device tree should have no knowledge of a firmware file name. What you should do instead is to have the driver generate the file name from the "compatible" property. You could use a lookup table in the driver, or have some algorithmic way of doing that, but you want the driver to have some form of intelligence to let it pick a different firmware image, e.g. when you have added new capabilities to the driver and the firmware but want to use an existing device tree. +Data structures +--- +Host memory : Directly accessed by the host to manage the MHI data structures +and buffers. The device accesses the host memory over the PCIe interface. + +Channel context array : All channel configurations are organized in channel +context data array. + +struct __packed mhi_chan_ctxt; +struct mhi_ctxt.chan_ctxt; + +Transfer rings : Used by host to schedule work items for a channel and organized +as a circular queue of transfer descriptors (TD). + +struct __packed mhi_tre; +struct mhi_chan.tre_ring; + This looks like you reinvented virtio. What are the reasons for not just using virtio directly as we do for other modem interfaces? +static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, + void *buf, + size_t size) +{ + u32 tx_status, val; + int i, ret; + void __iomem *base = mhi_cntrl->bhi; + rwlock_t *pm_lock = _cntrl->pm_lock; + dma_addr_t phys = dma_map_single(mhi_cntrl->dev, buf, size, +DMA_TO_DEVICE); Please don't name a dma address 'phys', it's very confusing ;-) +struct mhi_bus mhi_bus; One global instance? I suspec this duplicates data that is already in the bus_type structure, so just
Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface
On 04/27/2018 05:18 AM, Arnd Bergmann wrote: On Fri, Apr 27, 2018 at 4:23 AM, Sujeev Dias wrote: diff --git a/Documentation/devicetree/bindings/bus/mhi.txt b/Documentation/devicetree/bindings/bus/mhi.txt new file mode 100644 index 000..ea1b620 --- /dev/null +++ b/Documentation/devicetree/bindings/bus/mhi.txt @@ -0,0 +1,141 @@ +MHI Host Interface + +MHI used by the host to control and communicate with modem over +high speed peripheral bus. + +== +Node Structure +== + +Main node properties: + +- mhi,max-channels + Usage: required + Value type: + Definition: Maximum number of channels supported by this controller + +- mhi,chan-cfg + Usage: required + Value type: Array of + Definition: Array of tuples describe channel configuration. + 1st element: Physical channel number + 2nd element: Transfer ring length in elements + 3rd element: Event ring associated with this channel + 4th element: Channel direction as defined by enum dma_data_direction + 1 = UL data transfer + 2 = DL data transfer + 5th element: Channel doorbell mode configuration as defined by + enum MHI_BRSTMODE + 2 = burst mode disabled + 3 = burst mode enabled + 6th element: mhi doorbell configuration, valid only when burst mode + enabled. + 0 = Use default (device specific) polling configuration + For UL channels, value specifies the timer to poll MHI context + in milliseconds. + For DL channels, the threshold to poll the MHI context + in multiple of eight ring element. + 7th element: Channel execution enviornment as defined by enum MHI_EE + 1 = Bootloader stage + 2 = AMSS mode + 8th element: data transfer type accepted as defined by enum + MHI_XFER_TYPE + 0 = accept cpu address for buffer + 1 = accept skb + 2 = accept scatterlist + 3 = offload channel, does not accept any transfer type + 9th element: Bitwise configuration settings for the channel + Bit mask: + BIT(0) : LPM notify, this channel master requre lpm enter/exit + notifications. + BIT(1) : Offload channel, MHI host only involved in setting up + the data pipe. Not involved in active data transfer. + BIT(2) : Must switch to doorbell mode whenever MHI M0 state + transition happens. + BIT(3) : MHI bus driver pre-allocate buffer for this channel. + If set, clients not allowed to queue buffers. Valid only for DL + direction. + +- mhi,chan-names + Usage: required + Value type: Array of + Definition: Channel names configured in mhi,chan-cfg. I think the top-level structure would be better done by requiring a child for each channel and moving the mhi,chan-cfg into the children nodes, either as separate properties, or some of the fields combined into a 'reg' property. +- mhi,fw-name + Usage: optional + Value type: + Definition: Firmware image name to upload The device tree should have no knowledge of a firmware file name. What you should do instead is to have the driver generate the file name from the "compatible" property. You could use a lookup table in the driver, or have some algorithmic way of doing that, but you want the driver to have some form of intelligence to let it pick a different firmware image, e.g. when you have added new capabilities to the driver and the firmware but want to use an existing device tree. +Data structures +--- +Host memory : Directly accessed by the host to manage the MHI data structures +and buffers. The device accesses the host memory over the PCIe interface. + +Channel context array : All channel configurations are organized in channel +context data array. + +struct __packed mhi_chan_ctxt; +struct mhi_ctxt.chan_ctxt; + +Transfer rings : Used by host to schedule work items for a channel and organized +as a circular queue of transfer descriptors (TD). + +struct __packed mhi_tre; +struct mhi_chan.tre_ring; + This looks like you reinvented virtio. What are the reasons for not just using virtio directly as we do for other modem interfaces? +static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, + void *buf, + size_t size) +{ + u32 tx_status, val; + int i, ret; + void __iomem *base = mhi_cntrl->bhi; + rwlock_t *pm_lock = _cntrl->pm_lock; + dma_addr_t phys = dma_map_single(mhi_cntrl->dev, buf, size, +DMA_TO_DEVICE); Please don't name a dma address 'phys', it's very confusing ;-) +struct mhi_bus mhi_bus; One global instance? I suspec this duplicates data that is already in the bus_type structure, so just use that instead. +void mhi_
Re: [PATCH v1 2/4] mhi_bus: controller: MHI support for QCOM modems
On 04/27/2018 04:32 AM, Arnd Bergmann wrote: On Fri, Apr 27, 2018 at 4:23 AM, Sujeev Dias <sd...@codeaurora.org> wrote: QCOM PCIe based modems uses MHI as the communication protocol. MHI control driver is the bus master for such modems. As the bus master driver, it oversees power management operations such as suspend, resume, powering on and off the device. +- compatible + Usage: required + Value type: + Definition: "qcom,mhi" + +- qcom,pci-dev-id + Usage: optional + Value type: + Definition: PCIe device id of external modem to bind. If not set, any + device is compatible with this node. + +- qcom,pci-domain + Usage: required + Value type: + Definition: PCIe root complex external modem connected to + +- qcom,pci-bus + Usage: required + Value type: + Definition: PCIe bus external modem connected to + +- qcom,pci-slot + Usage: required + Value type: + Definition: PCIe slot as assigned by pci framework to external modem These don't seem to make any sense: You seem to have access to a regular pci_device already, so why do you need to duplicate the information about it in DT? I will remove the platform device, original hardware design we had a complicated power on sequence that require platform device to come up first and follow a strict power on sequence to power on modem before pci device can enumerate. I stored the BDF in DT to correlate the platform device with pci device. platform device is no longer needed so I can remove it. +- qcom,smmu-cfg + Usage: required + Value type: + Definition: Required SMMU configuration bitmask for PCIe bus. + BIT mask: + BIT(0) : Attach address mapping to endpoint device + BIT(1) : Set attribute S1_BYPASS + BIT(2) : Set attribute FAST + BIT(3) : Set attribute ATOMIC + BIT(4) : Set attribute FORCE_COHERENT + +- qcom,addr-win + Usage: required if SMMU S1 translation is enabled + Value type: Array of + Definition: Pair of values describing iova start and stop address Why do you need these? Can't that be handled by the PCI layer? I will move this to end point DT. PCIe end point driver does the iommu configuration +- qcom,msm-bus,name + Usage: required + Value type: + Definition: string representing the bus scale client name to register This probably belongs into a separate binding for the bus scale driver, right? Yes, this is for qcom bus scale driver which I don't think is upstreamed yet. Will confirm. +static struct pci_driver mhi_pcie_driver; Please try to reorder the symbols to avoid forward declarations. +static int mhi_platform_probe(struct platform_device *pdev) +{ + struct mhi_controller *mhi_cntrl; + struct mhi_dev *mhi_dev; + struct device_node *of_node = pdev->dev.of_node; + u64 addr_win[2]; + int ret; + + if (!of_node) + return -ENODEV; + + mhi_cntrl = mhi_alloc_controller(sizeof(*mhi_dev)); + if (!mhi_cntrl) + return -ENOMEM; + + mhi_dev = mhi_controller_get_devdata(mhi_cntrl); + + /* get pci bus topology for this node */ + ret = of_property_read_u32(of_node, "qcom,pci-dev-id", + _cntrl->dev_id); + if (ret) + mhi_cntrl->dev_id = PCI_ANY_ID; + + ret = of_property_read_u32(of_node, "qcom,pci-domain", + _cntrl->domain); + if (ret) + goto error_probe; + + ret = of_property_read_u32(of_node, "qcom,pci-bus", _cntrl->bus); + if (ret) + goto error_probe; + + ret = of_property_read_u32(of_node, "qcom,pci-slot", _cntrl->slot); + if (ret) + goto error_probe; Please explain what you are trying to do here, why do you register two device drivers? It looks like they both refer to the same hardware, so why isn't it sufficient to have the pci_driver? As I explained earlier, it's now. Original hardware design we had chicken egg situation where some driver has to come up and power on device before pcie enumeration can take place. Arnd -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Thanks again Sujeev -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v1 2/4] mhi_bus: controller: MHI support for QCOM modems
On 04/27/2018 04:32 AM, Arnd Bergmann wrote: On Fri, Apr 27, 2018 at 4:23 AM, Sujeev Dias wrote: QCOM PCIe based modems uses MHI as the communication protocol. MHI control driver is the bus master for such modems. As the bus master driver, it oversees power management operations such as suspend, resume, powering on and off the device. +- compatible + Usage: required + Value type: + Definition: "qcom,mhi" + +- qcom,pci-dev-id + Usage: optional + Value type: + Definition: PCIe device id of external modem to bind. If not set, any + device is compatible with this node. + +- qcom,pci-domain + Usage: required + Value type: + Definition: PCIe root complex external modem connected to + +- qcom,pci-bus + Usage: required + Value type: + Definition: PCIe bus external modem connected to + +- qcom,pci-slot + Usage: required + Value type: + Definition: PCIe slot as assigned by pci framework to external modem These don't seem to make any sense: You seem to have access to a regular pci_device already, so why do you need to duplicate the information about it in DT? I will remove the platform device, original hardware design we had a complicated power on sequence that require platform device to come up first and follow a strict power on sequence to power on modem before pci device can enumerate. I stored the BDF in DT to correlate the platform device with pci device. platform device is no longer needed so I can remove it. +- qcom,smmu-cfg + Usage: required + Value type: + Definition: Required SMMU configuration bitmask for PCIe bus. + BIT mask: + BIT(0) : Attach address mapping to endpoint device + BIT(1) : Set attribute S1_BYPASS + BIT(2) : Set attribute FAST + BIT(3) : Set attribute ATOMIC + BIT(4) : Set attribute FORCE_COHERENT + +- qcom,addr-win + Usage: required if SMMU S1 translation is enabled + Value type: Array of + Definition: Pair of values describing iova start and stop address Why do you need these? Can't that be handled by the PCI layer? I will move this to end point DT. PCIe end point driver does the iommu configuration +- qcom,msm-bus,name + Usage: required + Value type: + Definition: string representing the bus scale client name to register This probably belongs into a separate binding for the bus scale driver, right? Yes, this is for qcom bus scale driver which I don't think is upstreamed yet. Will confirm. +static struct pci_driver mhi_pcie_driver; Please try to reorder the symbols to avoid forward declarations. +static int mhi_platform_probe(struct platform_device *pdev) +{ + struct mhi_controller *mhi_cntrl; + struct mhi_dev *mhi_dev; + struct device_node *of_node = pdev->dev.of_node; + u64 addr_win[2]; + int ret; + + if (!of_node) + return -ENODEV; + + mhi_cntrl = mhi_alloc_controller(sizeof(*mhi_dev)); + if (!mhi_cntrl) + return -ENOMEM; + + mhi_dev = mhi_controller_get_devdata(mhi_cntrl); + + /* get pci bus topology for this node */ + ret = of_property_read_u32(of_node, "qcom,pci-dev-id", + _cntrl->dev_id); + if (ret) + mhi_cntrl->dev_id = PCI_ANY_ID; + + ret = of_property_read_u32(of_node, "qcom,pci-domain", + _cntrl->domain); + if (ret) + goto error_probe; + + ret = of_property_read_u32(of_node, "qcom,pci-bus", _cntrl->bus); + if (ret) + goto error_probe; + + ret = of_property_read_u32(of_node, "qcom,pci-slot", _cntrl->slot); + if (ret) + goto error_probe; Please explain what you are trying to do here, why do you register two device drivers? It looks like they both refer to the same hardware, so why isn't it sufficient to have the pci_driver? As I explained earlier, it's now. Original hardware design we had chicken egg situation where some driver has to come up and power on device before pcie enumeration can take place. Arnd -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Thanks again Sujeev -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v1 3/4] mhi_bus: dev: netdev: add network interface driver
On 04/27/2018 04:19 AM, Arnd Bergmann wrote: On Fri, Apr 27, 2018 at 4:23 AM, Sujeev Dias <sd...@codeaurora.org> wrote: MHI based net device driver is used for transferring IP traffic between host and modem. Driver allows clients to transfer data using standard network interface. Signed-off-by: Sujeev Dias <sd...@codeaurora.org> --- Documentation/devicetree/bindings/bus/mhi.txt | 36 ++ drivers/bus/Kconfig | 1 + drivers/bus/mhi/Makefile | 2 +- drivers/bus/mhi/devices/Kconfig | 10 + drivers/bus/mhi/devices/Makefile | 1 + drivers/bus/mhi/devices/mhi_netdev.c | 893 ++ Network drivers go into drivers/net/, not into the bus subsystem. You also need to Cc the netdev mailing list for review. will do, thanks. 6 files changed, 942 insertions(+), 1 deletion(-) create mode 100644 drivers/bus/mhi/devices/Kconfig create mode 100644 drivers/bus/mhi/devices/Makefile create mode 100644 drivers/bus/mhi/devices/mhi_netdev.c diff --git a/Documentation/devicetree/bindings/bus/mhi.txt b/Documentation/devicetree/bindings/bus/mhi.txt index ea1b620..172ae7b 100644 --- a/Documentation/devicetree/bindings/bus/mhi.txt +++ b/Documentation/devicetree/bindings/bus/mhi.txt @@ -139,3 +139,39 @@ mhi_controller { }; }; + + +Children Devices + + +MHI netdev properties + +- mhi,chan + Usage: required + Value type: + Definition: Channel name MHI netdev support +- mhi,mru + Usage: required + Value type: + Definition: Largest packet size interface can receive in bytes. + +- mhi,interface-name + Usage: optional + Value type: + Definition: Interface name to be given so clients can identify it + +- mhi,recycle-buf + Usage: optional + Value type: + Definition: Set true if interface support recycling buffers. + +Example: + + +mhi_rmnet@0 { + mhi,chan = "IP_HW0"; + mhi,interface-name = "rmnet_mhi"; + mhi,mru = <0x4000>; +}; Who defines the "IP_HW0" and "rmnet_mhi" strings? Shouldn't there be a "compatible" property? IP_HW0 is the a dedicated channel for IP traffic. It's defined by MHI specification. Supported channel names are fixed and dedicated per device. Interface name is a network iface name given so clients can identify the netdevice under /net/. Similar how pci framework bind DT based on bdf with pci end point driver, MHI bus uses mhi,chan property to bind children DT node before calling probe. mhi_main.c/mhi_create_device() mhi_main.c/mhi_create_device() /* add if there is a matching DT node */ controller = mhi_cntrl->of_node; for_each_available_child_of_node(controller, node) { ret = of_property_read_string(node, "mhi,chan", _name); if (ret) continue; if (!strcmp(mhi_dev->chan_name, dt_name)) mhi_dev->dev.of_node = node; +#define MHI_NETDEV_DRIVER_NAME "mhi_netdev" +#define WATCHDOG_TIMEOUT (30 * HZ) + +#ifdef CONFIG_MHI_DEBUG + +#define MHI_ASSERT(cond, msg) do { \ + if (cond) \ + panic(msg); \ +} while (0) + +#define MSG_VERB(fmt, ...) do { \ + if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_VERBOSE) \ + pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__);\ +} while (0) + +#define MSG_LOG(fmt, ...) do { \ + if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_INFO) \ + pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__);\ +} while (0) + +#define MSG_ERR(fmt, ...) do { \ + if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_ERROR) \ + pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \ +} while (0) + Please remove these macros and use the normal kernel helpers we have. Will do on next patch set. +struct mhi_stats { + u32 rx_int; + u32 tx_full; + u32 tx_pkts; + u32 rx_budget_overflow; + u32 rx_frag; + u32 alloc_failed; +}; + +/* important: do not exceed sk_buf->cb (48 bytes) */ +struct mhi_skb_priv { + void *buf; + size_t size; + struct mhi_netdev *mhi_netdev; +}; Shouldn't all three members already be part of an skb? You initialize them as + u32 cur_mru = mhi_netdev->mru; + skb_priv = (struct mhi_skb_priv *)skb->cb; + skb_priv->buf = skb->data; + skb_priv->size = cur_mru; + skb_priv->mhi_netdev = mhi_netdev; so I think you can remove the structure completely. Will confirm and remove it if it's not needed. +struct mhi_netdev { + int alias; + struct mhi_device *mhi_dev; + spinlock_t rx_lock; + bool enabled; + rwlock_t pm_lock; /* state change lock */ + int (*rx_queue)(struct mhi_netdev *mhi_netdev, gfp_t gfp_t); + struct work_struct alloc_work
Re: [PATCH v1 3/4] mhi_bus: dev: netdev: add network interface driver
On 04/27/2018 04:19 AM, Arnd Bergmann wrote: On Fri, Apr 27, 2018 at 4:23 AM, Sujeev Dias wrote: MHI based net device driver is used for transferring IP traffic between host and modem. Driver allows clients to transfer data using standard network interface. Signed-off-by: Sujeev Dias --- Documentation/devicetree/bindings/bus/mhi.txt | 36 ++ drivers/bus/Kconfig | 1 + drivers/bus/mhi/Makefile | 2 +- drivers/bus/mhi/devices/Kconfig | 10 + drivers/bus/mhi/devices/Makefile | 1 + drivers/bus/mhi/devices/mhi_netdev.c | 893 ++ Network drivers go into drivers/net/, not into the bus subsystem. You also need to Cc the netdev mailing list for review. will do, thanks. 6 files changed, 942 insertions(+), 1 deletion(-) create mode 100644 drivers/bus/mhi/devices/Kconfig create mode 100644 drivers/bus/mhi/devices/Makefile create mode 100644 drivers/bus/mhi/devices/mhi_netdev.c diff --git a/Documentation/devicetree/bindings/bus/mhi.txt b/Documentation/devicetree/bindings/bus/mhi.txt index ea1b620..172ae7b 100644 --- a/Documentation/devicetree/bindings/bus/mhi.txt +++ b/Documentation/devicetree/bindings/bus/mhi.txt @@ -139,3 +139,39 @@ mhi_controller { }; }; + + +Children Devices + + +MHI netdev properties + +- mhi,chan + Usage: required + Value type: + Definition: Channel name MHI netdev support +- mhi,mru + Usage: required + Value type: + Definition: Largest packet size interface can receive in bytes. + +- mhi,interface-name + Usage: optional + Value type: + Definition: Interface name to be given so clients can identify it + +- mhi,recycle-buf + Usage: optional + Value type: + Definition: Set true if interface support recycling buffers. + +Example: + + +mhi_rmnet@0 { + mhi,chan = "IP_HW0"; + mhi,interface-name = "rmnet_mhi"; + mhi,mru = <0x4000>; +}; Who defines the "IP_HW0" and "rmnet_mhi" strings? Shouldn't there be a "compatible" property? IP_HW0 is the a dedicated channel for IP traffic. It's defined by MHI specification. Supported channel names are fixed and dedicated per device. Interface name is a network iface name given so clients can identify the netdevice under /net/. Similar how pci framework bind DT based on bdf with pci end point driver, MHI bus uses mhi,chan property to bind children DT node before calling probe. mhi_main.c/mhi_create_device() mhi_main.c/mhi_create_device() /* add if there is a matching DT node */ controller = mhi_cntrl->of_node; for_each_available_child_of_node(controller, node) { ret = of_property_read_string(node, "mhi,chan", _name); if (ret) continue; if (!strcmp(mhi_dev->chan_name, dt_name)) mhi_dev->dev.of_node = node; +#define MHI_NETDEV_DRIVER_NAME "mhi_netdev" +#define WATCHDOG_TIMEOUT (30 * HZ) + +#ifdef CONFIG_MHI_DEBUG + +#define MHI_ASSERT(cond, msg) do { \ + if (cond) \ + panic(msg); \ +} while (0) + +#define MSG_VERB(fmt, ...) do { \ + if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_VERBOSE) \ + pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__);\ +} while (0) + +#define MSG_LOG(fmt, ...) do { \ + if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_INFO) \ + pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__);\ +} while (0) + +#define MSG_ERR(fmt, ...) do { \ + if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_ERROR) \ + pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \ +} while (0) + Please remove these macros and use the normal kernel helpers we have. Will do on next patch set. +struct mhi_stats { + u32 rx_int; + u32 tx_full; + u32 tx_pkts; + u32 rx_budget_overflow; + u32 rx_frag; + u32 alloc_failed; +}; + +/* important: do not exceed sk_buf->cb (48 bytes) */ +struct mhi_skb_priv { + void *buf; + size_t size; + struct mhi_netdev *mhi_netdev; +}; Shouldn't all three members already be part of an skb? You initialize them as + u32 cur_mru = mhi_netdev->mru; + skb_priv = (struct mhi_skb_priv *)skb->cb; + skb_priv->buf = skb->data; + skb_priv->size = cur_mru; + skb_priv->mhi_netdev = mhi_netdev; so I think you can remove the structure completely. Will confirm and remove it if it's not needed. +struct mhi_netdev { + int alias; + struct mhi_device *mhi_dev; + spinlock_t rx_lock; + bool enabled; + rwlock_t pm_lock; /* state change lock */ + int (*rx_queue)(struct mhi_netdev *mhi_netdev, gfp_t gfp_t); + struct work_struct alloc_work; + int wake; + + struct sk_buff_head rx_allocated;
Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface
Thanks for quick feedback On 04/27/2018 12:22 AM, Greg Kroah-Hartman wrote: On Thu, Apr 26, 2018 at 07:23:28PM -0700, Sujeev Dias wrote: MHI Host Interface is a communication protocol to be used by the host to control and communcate with modem over a high speed peripheral bus. This module will allow host to communicate with external devices that support MHI protocol. Signed-off-by: Sujeev Dias <sd...@codeaurora.org> No one else has ever reviewed this code before? That's not good, please at the very least, have someone else at your company go over it first. I don't want to be the ones having to point out all of the "obvious" issues :) This code has gone thru rigorous code review and testing, before I submit next patch I will have multiple people sign off on it. --- Documentation/00-INDEX|2 + Documentation/devicetree/bindings/bus/mhi.txt | 141 +++ Documentation/mhi.txt | 235 drivers/bus/Kconfig | 17 + drivers/bus/Makefile |1 + drivers/bus/mhi/Makefile |8 + drivers/bus/mhi/core/Makefile |1 + drivers/bus/mhi/core/mhi_boot.c | 593 ++ drivers/bus/mhi/core/mhi_dtr.c| 177 +++ drivers/bus/mhi/core/mhi_init.c | 1290 + drivers/bus/mhi/core/mhi_internal.h | 732 drivers/bus/mhi/core/mhi_main.c | 1476 + drivers/bus/mhi/core/mhi_pm.c | 1177 include/linux/mhi.h | 694 include/linux/mod_devicetable.h | 11 + 15 files changed, 6555 insertions(+) And a 6555 line patch is a bit hard to consume all at once. Can't this be split up into much more reviewable chunks? Look at how some of the other new bus subsystems got added to the tree recently. They were submitted in longer patch series, but smaller sized patches individually. That makes things much easier to review. For example, there is no reason your debugfs stuff needs to be in this initial patch. That should be in a separate one, right? Same for firmware download. Please take the time to break this up into logical steps. Like my son's math teacher keeps telling him, "show your work, not just an answer at the bottom of the page". Also, it is required by the DT maintainers to split that file alone up into a separate patch to be even considered for merging. One thing I can tell you right now that isn't acceptable: That is interesting because internally it's separated, and I squash them thinking it was preferred. I will separate them out to functional blocks +#ifdef CONFIG_MHI_DEBUG Don't have a separate config option for debugging. No one will enable it, which makes it pointless. Everything has to be dynamic these days. Intention was to completely compile out MHI_VERB messages because we have those messages in data path. For release build, we wanted to reduce as much mips as possible. However, for debugging these messages are extremely helpful. I will look into tracepoints... + +#define MHI_VERB(fmt, ...) do { \ + if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_VERBOSE) \ + pr_debug("[D][%s] " fmt, __func__, ##__VA_ARGS__);\ +} while (0) + +#else + +#define MHI_VERB(fmt, ...) + +#endif + +#define MHI_LOG(fmt, ...) do { \ + if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_INFO) \ + pr_info("[I][%s] " fmt, __func__, ##__VA_ARGS__);\ +} while (0) + +#define MHI_ERR(fmt, ...) do { \ + if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_ERROR) \ + pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \ +} while (0) + +#define MHI_CRITICAL(fmt, ...) do { \ + if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_CRITICAL) \ + pr_alert("[C][%s] " fmt, __func__, ##__VA_ARGS__); \ +} while (0) + And do not roll your own debugging/logging macros. Use what is given to you (dev_info(), dev_err(), dev_dbg()), they are there for a reason. By going around them, you circumvent the whole of the kernel logging infrastructure and declare that your tiny bus is somehow more "special" than it. And I doubt you want to make such a statement :) well :).. I will remove them in next revision. thanks, greg k-h -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Thanks Sujeev -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface
Thanks for quick feedback On 04/27/2018 12:22 AM, Greg Kroah-Hartman wrote: On Thu, Apr 26, 2018 at 07:23:28PM -0700, Sujeev Dias wrote: MHI Host Interface is a communication protocol to be used by the host to control and communcate with modem over a high speed peripheral bus. This module will allow host to communicate with external devices that support MHI protocol. Signed-off-by: Sujeev Dias No one else has ever reviewed this code before? That's not good, please at the very least, have someone else at your company go over it first. I don't want to be the ones having to point out all of the "obvious" issues :) This code has gone thru rigorous code review and testing, before I submit next patch I will have multiple people sign off on it. --- Documentation/00-INDEX|2 + Documentation/devicetree/bindings/bus/mhi.txt | 141 +++ Documentation/mhi.txt | 235 drivers/bus/Kconfig | 17 + drivers/bus/Makefile |1 + drivers/bus/mhi/Makefile |8 + drivers/bus/mhi/core/Makefile |1 + drivers/bus/mhi/core/mhi_boot.c | 593 ++ drivers/bus/mhi/core/mhi_dtr.c| 177 +++ drivers/bus/mhi/core/mhi_init.c | 1290 + drivers/bus/mhi/core/mhi_internal.h | 732 drivers/bus/mhi/core/mhi_main.c | 1476 + drivers/bus/mhi/core/mhi_pm.c | 1177 include/linux/mhi.h | 694 include/linux/mod_devicetable.h | 11 + 15 files changed, 6555 insertions(+) And a 6555 line patch is a bit hard to consume all at once. Can't this be split up into much more reviewable chunks? Look at how some of the other new bus subsystems got added to the tree recently. They were submitted in longer patch series, but smaller sized patches individually. That makes things much easier to review. For example, there is no reason your debugfs stuff needs to be in this initial patch. That should be in a separate one, right? Same for firmware download. Please take the time to break this up into logical steps. Like my son's math teacher keeps telling him, "show your work, not just an answer at the bottom of the page". Also, it is required by the DT maintainers to split that file alone up into a separate patch to be even considered for merging. One thing I can tell you right now that isn't acceptable: That is interesting because internally it's separated, and I squash them thinking it was preferred. I will separate them out to functional blocks +#ifdef CONFIG_MHI_DEBUG Don't have a separate config option for debugging. No one will enable it, which makes it pointless. Everything has to be dynamic these days. Intention was to completely compile out MHI_VERB messages because we have those messages in data path. For release build, we wanted to reduce as much mips as possible. However, for debugging these messages are extremely helpful. I will look into tracepoints... + +#define MHI_VERB(fmt, ...) do { \ + if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_VERBOSE) \ + pr_debug("[D][%s] " fmt, __func__, ##__VA_ARGS__);\ +} while (0) + +#else + +#define MHI_VERB(fmt, ...) + +#endif + +#define MHI_LOG(fmt, ...) do { \ + if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_INFO) \ + pr_info("[I][%s] " fmt, __func__, ##__VA_ARGS__);\ +} while (0) + +#define MHI_ERR(fmt, ...) do { \ + if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_ERROR) \ + pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \ +} while (0) + +#define MHI_CRITICAL(fmt, ...) do { \ + if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_CRITICAL) \ + pr_alert("[C][%s] " fmt, __func__, ##__VA_ARGS__); \ +} while (0) + And do not roll your own debugging/logging macros. Use what is given to you (dev_info(), dev_err(), dev_dbg()), they are there for a reason. By going around them, you circumvent the whole of the kernel logging infrastructure and declare that your tiny bus is somehow more "special" than it. And I doubt you want to make such a statement :) well :).. I will remove them in next revision. thanks, greg k-h -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Thanks Sujeev -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
MHI initial design review
Hi Greg Kroah-Hartman\All This is the initial submit of Modem Host Interface (MHI) stack for upstream consideration. MHI is a communication protocol to communicate with external Qualcomm modems and Wi-Fi chipsets over high speed peripheral buses. Even though MHI doesn’t dictate underlying physical layer, protocol and mhi stack is structured for PCIe based devices. For additional details related to MHI interface please see Documentation/mhi.txt. MHI stack partitioned into three main components: 1. Core layer handles all MHI protocol specific actions such as firmware download, and data transfer /drivers/bus/mhi/core/* 2. Control layer bus master, manages power transitions of external modem. /drivers/bus/mhi/controllers/* 3. Device drivers MHI channels (physical transport channels) exposed as mhi devices for clients to send and receive data. /drivers/bus/mhi/device/* There are three ways which clients can interface with MHI framework to send and receive data from external modem. 1. Register directly with mhi core layer as a mhi device driver 2. User space clients can interface via mhi_uci driver. 3. For net traffic, mhi_netdev can be used. Can you please do a high-level design review of the MHI driver and let me know if I need to make any design changes before the drivers can be considered for upstream. Thanks Sujeev
MHI initial design review
Hi Greg Kroah-Hartman\All This is the initial submit of Modem Host Interface (MHI) stack for upstream consideration. MHI is a communication protocol to communicate with external Qualcomm modems and Wi-Fi chipsets over high speed peripheral buses. Even though MHI doesn’t dictate underlying physical layer, protocol and mhi stack is structured for PCIe based devices. For additional details related to MHI interface please see Documentation/mhi.txt. MHI stack partitioned into three main components: 1. Core layer handles all MHI protocol specific actions such as firmware download, and data transfer /drivers/bus/mhi/core/* 2. Control layer bus master, manages power transitions of external modem. /drivers/bus/mhi/controllers/* 3. Device drivers MHI channels (physical transport channels) exposed as mhi devices for clients to send and receive data. /drivers/bus/mhi/device/* There are three ways which clients can interface with MHI framework to send and receive data from external modem. 1. Register directly with mhi core layer as a mhi device driver 2. User space clients can interface via mhi_uci driver. 3. For net traffic, mhi_netdev can be used. Can you please do a high-level design review of the MHI driver and let me know if I need to make any design changes before the drivers can be considered for upstream. Thanks Sujeev
[PATCH v1 2/4] mhi_bus: controller: MHI support for QCOM modems
QCOM PCIe based modems uses MHI as the communication protocol. MHI control driver is the bus master for such modems. As the bus master driver, it oversees power management operations such as suspend, resume, powering on and off the device. Signed-off-by: Sujeev Dias <sd...@codeaurora.org> --- Documentation/devicetree/bindings/bus/mhi_qcom.txt | 110 drivers/bus/Kconfig| 1 + drivers/bus/mhi/Makefile | 2 +- drivers/bus/mhi/controllers/Kconfig| 10 + drivers/bus/mhi/controllers/Makefile | 1 + drivers/bus/mhi/controllers/mhi_qcom.c | 686 + drivers/bus/mhi/controllers/mhi_qcom.h | 85 +++ 7 files changed, 894 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/bus/mhi_qcom.txt create mode 100644 drivers/bus/mhi/controllers/Kconfig create mode 100644 drivers/bus/mhi/controllers/Makefile create mode 100644 drivers/bus/mhi/controllers/mhi_qcom.c create mode 100644 drivers/bus/mhi/controllers/mhi_qcom.h diff --git a/Documentation/devicetree/bindings/bus/mhi_qcom.txt b/Documentation/devicetree/bindings/bus/mhi_qcom.txt new file mode 100644 index 000..c0f8d86 --- /dev/null +++ b/Documentation/devicetree/bindings/bus/mhi_qcom.txt @@ -0,0 +1,110 @@ +Qualcomm Technologies Inc MHI Bus controller + +MHI control driver enables clients to communicate with external mode +using MHI protocol. + +== +Node Structure +== + +Main node properties: + +- compatible + Usage: required + Value type: + Definition: "qcom,mhi" + +- qcom,pci-dev-id + Usage: optional + Value type: + Definition: PCIe device id of external modem to bind. If not set, any + device is compatible with this node. + +- qcom,pci-domain + Usage: required + Value type: + Definition: PCIe root complex external modem connected to + +- qcom,pci-bus + Usage: required + Value type: + Definition: PCIe bus external modem connected to + +- qcom,pci-slot + Usage: required + Value type: + Definition: PCIe slot as assigned by pci framework to external modem + +- qcom,smmu-cfg + Usage: required + Value type: + Definition: Required SMMU configuration bitmask for PCIe bus. + BIT mask: + BIT(0) : Attach address mapping to endpoint device + BIT(1) : Set attribute S1_BYPASS + BIT(2) : Set attribute FAST + BIT(3) : Set attribute ATOMIC + BIT(4) : Set attribute FORCE_COHERENT + +- qcom,addr-win + Usage: required if SMMU S1 translation is enabled + Value type: Array of + Definition: Pair of values describing iova start and stop address + +- qcom,msm-bus,name + Usage: required + Value type: + Definition: string representing the bus scale client name to register + +- qcom,msm-bus,num-cases + Usage: required + Value type: + Definition: Must be set to two, MHI support two scales + +- qcom,msm-bus,num-paths + Usage: required + Value type: + Definition: Total number of master-slave pairs MHI host will vote. Must be set + to one. + +- qcom,msm-bus,vectors-KBps + Usage: required + Value type: Array of + Definition: Array of tuples which define the bus bandwidth requirements. + Each tuple is of length 4, values are master-id, slave-id, + arbitrated bandwidth in KBps, and instantaneous bandwidth in + KBps. + +- esoc-names + Usage: optional + Value type: + Definition: if external modem managed by esoc framework, set string to "mdm" + +- esoc-0 + Usage: required if device is managed by esoc framework + Value type: phandle + Definition: A esoc phandle pointing to external modem + +- MHI bus settings + Usage: required + Values: as defined by mhi.txt + Definition: Per definition of devicetree/bindings/bus/mhi.txt, define device + specific MHI configuration parameters. + + +Example: + +qcom,mhi { + compatible = "qcom,mhi"; + qcom,pci-domain = <0>; + qcom,pci-bus = <1>; + qcom,pci-slot = <0>; + qcom,smmu-cfg = <0x3d>; + qcom,addr-win = <0x0 0x2000 0x0 0x3fff>; + qcom,msm-bus,name = "mhi"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = <45 512 0 0>, + <45 512 12 65000>; + +}; diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index e15d56d..fb28002 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -189,5 +189,6 @@ config MHI_DEBUG will be logged. source "drivers/bus/fsl-mc/Kconfig" +source drivers/bus/mhi/controllers/Kconfig endmenu diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile index 9f8f3ac..c6a2a91 100644 --- a/drivers/bus/mhi/Makefile +++ b/drivers/bus/mhi/Makefile @@ -4,5 +4,5 @@ # core layer obj-y += core/ -#obj-y
[PATCH v1 2/4] mhi_bus: controller: MHI support for QCOM modems
QCOM PCIe based modems uses MHI as the communication protocol. MHI control driver is the bus master for such modems. As the bus master driver, it oversees power management operations such as suspend, resume, powering on and off the device. Signed-off-by: Sujeev Dias --- Documentation/devicetree/bindings/bus/mhi_qcom.txt | 110 drivers/bus/Kconfig| 1 + drivers/bus/mhi/Makefile | 2 +- drivers/bus/mhi/controllers/Kconfig| 10 + drivers/bus/mhi/controllers/Makefile | 1 + drivers/bus/mhi/controllers/mhi_qcom.c | 686 + drivers/bus/mhi/controllers/mhi_qcom.h | 85 +++ 7 files changed, 894 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/bus/mhi_qcom.txt create mode 100644 drivers/bus/mhi/controllers/Kconfig create mode 100644 drivers/bus/mhi/controllers/Makefile create mode 100644 drivers/bus/mhi/controllers/mhi_qcom.c create mode 100644 drivers/bus/mhi/controllers/mhi_qcom.h diff --git a/Documentation/devicetree/bindings/bus/mhi_qcom.txt b/Documentation/devicetree/bindings/bus/mhi_qcom.txt new file mode 100644 index 000..c0f8d86 --- /dev/null +++ b/Documentation/devicetree/bindings/bus/mhi_qcom.txt @@ -0,0 +1,110 @@ +Qualcomm Technologies Inc MHI Bus controller + +MHI control driver enables clients to communicate with external mode +using MHI protocol. + +== +Node Structure +== + +Main node properties: + +- compatible + Usage: required + Value type: + Definition: "qcom,mhi" + +- qcom,pci-dev-id + Usage: optional + Value type: + Definition: PCIe device id of external modem to bind. If not set, any + device is compatible with this node. + +- qcom,pci-domain + Usage: required + Value type: + Definition: PCIe root complex external modem connected to + +- qcom,pci-bus + Usage: required + Value type: + Definition: PCIe bus external modem connected to + +- qcom,pci-slot + Usage: required + Value type: + Definition: PCIe slot as assigned by pci framework to external modem + +- qcom,smmu-cfg + Usage: required + Value type: + Definition: Required SMMU configuration bitmask for PCIe bus. + BIT mask: + BIT(0) : Attach address mapping to endpoint device + BIT(1) : Set attribute S1_BYPASS + BIT(2) : Set attribute FAST + BIT(3) : Set attribute ATOMIC + BIT(4) : Set attribute FORCE_COHERENT + +- qcom,addr-win + Usage: required if SMMU S1 translation is enabled + Value type: Array of + Definition: Pair of values describing iova start and stop address + +- qcom,msm-bus,name + Usage: required + Value type: + Definition: string representing the bus scale client name to register + +- qcom,msm-bus,num-cases + Usage: required + Value type: + Definition: Must be set to two, MHI support two scales + +- qcom,msm-bus,num-paths + Usage: required + Value type: + Definition: Total number of master-slave pairs MHI host will vote. Must be set + to one. + +- qcom,msm-bus,vectors-KBps + Usage: required + Value type: Array of + Definition: Array of tuples which define the bus bandwidth requirements. + Each tuple is of length 4, values are master-id, slave-id, + arbitrated bandwidth in KBps, and instantaneous bandwidth in + KBps. + +- esoc-names + Usage: optional + Value type: + Definition: if external modem managed by esoc framework, set string to "mdm" + +- esoc-0 + Usage: required if device is managed by esoc framework + Value type: phandle + Definition: A esoc phandle pointing to external modem + +- MHI bus settings + Usage: required + Values: as defined by mhi.txt + Definition: Per definition of devicetree/bindings/bus/mhi.txt, define device + specific MHI configuration parameters. + + +Example: + +qcom,mhi { + compatible = "qcom,mhi"; + qcom,pci-domain = <0>; + qcom,pci-bus = <1>; + qcom,pci-slot = <0>; + qcom,smmu-cfg = <0x3d>; + qcom,addr-win = <0x0 0x2000 0x0 0x3fff>; + qcom,msm-bus,name = "mhi"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = <45 512 0 0>, + <45 512 12 65000>; + +}; diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index e15d56d..fb28002 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -189,5 +189,6 @@ config MHI_DEBUG will be logged. source "drivers/bus/fsl-mc/Kconfig" +source drivers/bus/mhi/controllers/Kconfig endmenu diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile index 9f8f3ac..c6a2a91 100644 --- a/drivers/bus/mhi/Makefile +++ b/drivers/bus/mhi/Makefile @@ -4,5 +4,5 @@ # core layer obj-y += core/ -#obj-y += controllers/ +obj-y += controll
[PATCH v1 3/4] mhi_bus: dev: netdev: add network interface driver
MHI based net device driver is used for transferring IP traffic between host and modem. Driver allows clients to transfer data using standard network interface. Signed-off-by: Sujeev Dias <sd...@codeaurora.org> --- Documentation/devicetree/bindings/bus/mhi.txt | 36 ++ drivers/bus/Kconfig | 1 + drivers/bus/mhi/Makefile | 2 +- drivers/bus/mhi/devices/Kconfig | 10 + drivers/bus/mhi/devices/Makefile | 1 + drivers/bus/mhi/devices/mhi_netdev.c | 893 ++ 6 files changed, 942 insertions(+), 1 deletion(-) create mode 100644 drivers/bus/mhi/devices/Kconfig create mode 100644 drivers/bus/mhi/devices/Makefile create mode 100644 drivers/bus/mhi/devices/mhi_netdev.c diff --git a/Documentation/devicetree/bindings/bus/mhi.txt b/Documentation/devicetree/bindings/bus/mhi.txt index ea1b620..172ae7b 100644 --- a/Documentation/devicetree/bindings/bus/mhi.txt +++ b/Documentation/devicetree/bindings/bus/mhi.txt @@ -139,3 +139,39 @@ mhi_controller { }; }; + + +Children Devices + + +MHI netdev properties + +- mhi,chan + Usage: required + Value type: + Definition: Channel name MHI netdev support + +- mhi,mru + Usage: required + Value type: + Definition: Largest packet size interface can receive in bytes. + +- mhi,interface-name + Usage: optional + Value type: + Definition: Interface name to be given so clients can identify it + +- mhi,recycle-buf + Usage: optional + Value type: + Definition: Set true if interface support recycling buffers. + + +Example: + + +mhi_rmnet@0 { + mhi,chan = "IP_HW0"; + mhi,interface-name = "rmnet_mhi"; + mhi,mru = <0x4000>; +}; diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index fb28002..cc03762 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -190,5 +190,6 @@ config MHI_DEBUG source "drivers/bus/fsl-mc/Kconfig" source drivers/bus/mhi/controllers/Kconfig +source drivers/bus/mhi/devices/Kconfig endmenu diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile index c6a2a91..2382e04 100644 --- a/drivers/bus/mhi/Makefile +++ b/drivers/bus/mhi/Makefile @@ -5,4 +5,4 @@ # core layer obj-y += core/ obj-y += controllers/ -#obj-y += devices/ +obj-y += devices/ diff --git a/drivers/bus/mhi/devices/Kconfig b/drivers/bus/mhi/devices/Kconfig new file mode 100644 index 000..40f964d --- /dev/null +++ b/drivers/bus/mhi/devices/Kconfig @@ -0,0 +1,10 @@ +menu "MHI device support" + +config MHI_NETDEV + tristate "MHI NETDEV" + depends on MHI_BUS + help + MHI based net device driver for transferring IP traffic + between host and modem. By enabling this driver, clients + can transfer data using standard network interface. +endmenu diff --git a/drivers/bus/mhi/devices/Makefile b/drivers/bus/mhi/devices/Makefile new file mode 100644 index 000..ee12a64 --- /dev/null +++ b/drivers/bus/mhi/devices/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_MHI_NETDEV) +=mhi_netdev.o diff --git a/drivers/bus/mhi/devices/mhi_netdev.c b/drivers/bus/mhi/devices/mhi_netdev.c new file mode 100644 index 000..23881a9 --- /dev/null +++ b/drivers/bus/mhi/devices/mhi_netdev.c @@ -0,0 +1,893 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MHI_NETDEV_DRIVER_NAME "mhi_netdev" +#define WATCHDOG_TIMEOUT (30 * HZ) + +#ifdef CONFIG_MHI_DEBUG + +#define MHI_ASSERT(cond, msg) do { \ + if (cond) \ + panic(msg); \ +} while (0) + +#define MSG_VERB(fmt, ...) do { \ + if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_VERBOSE) \ + pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__);\ +} while (0) + +#else + +#define MHI_ASSERT(cond, msg) do { \ + if (cond) { \ + MSG_ERR(msg); \ + WARN_ON(cond); \ + } \ +} while (0) + +#define MSG_VERB(fmt, ...) + +#endif + +#define MSG_LOG(fmt, ...) do { \ + if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_INFO) \ + pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__);\ +} while (0) + +#define MSG_ERR(fmt, ...) do { \ + if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_ERROR) \ + pr_err("[E][%s] "
[PATCH v1 3/4] mhi_bus: dev: netdev: add network interface driver
MHI based net device driver is used for transferring IP traffic between host and modem. Driver allows clients to transfer data using standard network interface. Signed-off-by: Sujeev Dias --- Documentation/devicetree/bindings/bus/mhi.txt | 36 ++ drivers/bus/Kconfig | 1 + drivers/bus/mhi/Makefile | 2 +- drivers/bus/mhi/devices/Kconfig | 10 + drivers/bus/mhi/devices/Makefile | 1 + drivers/bus/mhi/devices/mhi_netdev.c | 893 ++ 6 files changed, 942 insertions(+), 1 deletion(-) create mode 100644 drivers/bus/mhi/devices/Kconfig create mode 100644 drivers/bus/mhi/devices/Makefile create mode 100644 drivers/bus/mhi/devices/mhi_netdev.c diff --git a/Documentation/devicetree/bindings/bus/mhi.txt b/Documentation/devicetree/bindings/bus/mhi.txt index ea1b620..172ae7b 100644 --- a/Documentation/devicetree/bindings/bus/mhi.txt +++ b/Documentation/devicetree/bindings/bus/mhi.txt @@ -139,3 +139,39 @@ mhi_controller { }; }; + + +Children Devices + + +MHI netdev properties + +- mhi,chan + Usage: required + Value type: + Definition: Channel name MHI netdev support + +- mhi,mru + Usage: required + Value type: + Definition: Largest packet size interface can receive in bytes. + +- mhi,interface-name + Usage: optional + Value type: + Definition: Interface name to be given so clients can identify it + +- mhi,recycle-buf + Usage: optional + Value type: + Definition: Set true if interface support recycling buffers. + + +Example: + + +mhi_rmnet@0 { + mhi,chan = "IP_HW0"; + mhi,interface-name = "rmnet_mhi"; + mhi,mru = <0x4000>; +}; diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index fb28002..cc03762 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -190,5 +190,6 @@ config MHI_DEBUG source "drivers/bus/fsl-mc/Kconfig" source drivers/bus/mhi/controllers/Kconfig +source drivers/bus/mhi/devices/Kconfig endmenu diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile index c6a2a91..2382e04 100644 --- a/drivers/bus/mhi/Makefile +++ b/drivers/bus/mhi/Makefile @@ -5,4 +5,4 @@ # core layer obj-y += core/ obj-y += controllers/ -#obj-y += devices/ +obj-y += devices/ diff --git a/drivers/bus/mhi/devices/Kconfig b/drivers/bus/mhi/devices/Kconfig new file mode 100644 index 000..40f964d --- /dev/null +++ b/drivers/bus/mhi/devices/Kconfig @@ -0,0 +1,10 @@ +menu "MHI device support" + +config MHI_NETDEV + tristate "MHI NETDEV" + depends on MHI_BUS + help + MHI based net device driver for transferring IP traffic + between host and modem. By enabling this driver, clients + can transfer data using standard network interface. +endmenu diff --git a/drivers/bus/mhi/devices/Makefile b/drivers/bus/mhi/devices/Makefile new file mode 100644 index 000..ee12a64 --- /dev/null +++ b/drivers/bus/mhi/devices/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_MHI_NETDEV) +=mhi_netdev.o diff --git a/drivers/bus/mhi/devices/mhi_netdev.c b/drivers/bus/mhi/devices/mhi_netdev.c new file mode 100644 index 000..23881a9 --- /dev/null +++ b/drivers/bus/mhi/devices/mhi_netdev.c @@ -0,0 +1,893 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MHI_NETDEV_DRIVER_NAME "mhi_netdev" +#define WATCHDOG_TIMEOUT (30 * HZ) + +#ifdef CONFIG_MHI_DEBUG + +#define MHI_ASSERT(cond, msg) do { \ + if (cond) \ + panic(msg); \ +} while (0) + +#define MSG_VERB(fmt, ...) do { \ + if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_VERBOSE) \ + pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__);\ +} while (0) + +#else + +#define MHI_ASSERT(cond, msg) do { \ + if (cond) { \ + MSG_ERR(msg); \ + WARN_ON(cond); \ + } \ +} while (0) + +#define MSG_VERB(fmt, ...) + +#endif + +#define MSG_LOG(fmt, ...) do { \ + if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_INFO) \ + pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__);\ +} while (0) + +#define MSG_ERR(fmt, ...) do { \ + if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_ERROR) \ + pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS_
[PATCH v1 4/4] mhi_bus: dev: uci: add user space interface driver
This module allows user space clients to transfer data between external modem and host using standard file operations. Signed-off-by: Sujeev Dias <sd...@codeaurora.org> --- drivers/bus/mhi/devices/Kconfig | 9 + drivers/bus/mhi/devices/Makefile | 1 + drivers/bus/mhi/devices/mhi_uci.c | 662 ++ 3 files changed, 672 insertions(+) create mode 100644 drivers/bus/mhi/devices/mhi_uci.c diff --git a/drivers/bus/mhi/devices/Kconfig b/drivers/bus/mhi/devices/Kconfig index 40f964d..83b9673 100644 --- a/drivers/bus/mhi/devices/Kconfig +++ b/drivers/bus/mhi/devices/Kconfig @@ -7,4 +7,13 @@ config MHI_NETDEV MHI based net device driver for transferring IP traffic between host and modem. By enabling this driver, clients can transfer data using standard network interface. + +config MHI_UCI + tristate "MHI UCI" + depends on MHI_BUS + help + MHI based uci driver is for transferring data between host and + modem using standard file operations from user space. Open, read, + write, ioctl, and close operations are supported by this driver. + endmenu diff --git a/drivers/bus/mhi/devices/Makefile b/drivers/bus/mhi/devices/Makefile index ee12a64..300eed1 100644 --- a/drivers/bus/mhi/devices/Makefile +++ b/drivers/bus/mhi/devices/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_MHI_NETDEV) +=mhi_netdev.o +obj-$(CONFIG_MHI_UCI) +=mhi_uci.o diff --git a/drivers/bus/mhi/devices/mhi_uci.c b/drivers/bus/mhi/devices/mhi_uci.c new file mode 100644 index 000..11b7b1f --- /dev/null +++ b/drivers/bus/mhi/devices/mhi_uci.c @@ -0,0 +1,662 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_NAME "mhi" +#define MHI_UCI_DRIVER_NAME "mhi_uci" + +struct uci_chan { + wait_queue_head_t wq; + spinlock_t lock; + struct list_head pending; /* user space waiting to read */ + struct uci_buf *cur_buf; /* current buffer user space reading */ + size_t rx_size; +}; + +struct uci_buf { + void *data; + size_t len; + struct list_head node; +}; + +struct uci_dev { + struct list_head node; + dev_t devt; + struct device *dev; + struct mhi_device *mhi_dev; + const char *chan; + struct mutex mutex; /* sync open and close */ + struct uci_chan ul_chan; + struct uci_chan dl_chan; + size_t mtu; + int ref_count; + bool enabled; +}; + +struct mhi_uci_drv { + struct list_head head; + struct mutex lock; + struct class *class; + int major; + dev_t dev_t; +}; + +enum MHI_DEBUG_LEVEL msg_lvl = MHI_MSG_LVL_ERROR; + +#ifdef CONFIG_MHI_DEBUG + +#define MSG_VERB(fmt, ...) do { \ + if (msg_lvl <= MHI_MSG_LVL_VERBOSE) \ + pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#else + +#define MSG_VERB(fmt, ...) + +#endif + +#define MSG_LOG(fmt, ...) do { \ + if (msg_lvl <= MHI_MSG_LVL_INFO) \ + pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#define MSG_ERR(fmt, ...) do { \ + if (msg_lvl <= MHI_MSG_LVL_ERROR) \ + pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#define MAX_UCI_DEVICES (64) + +static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES); +static struct mhi_uci_drv mhi_uci_drv; + +static int mhi_queue_inbound(struct uci_dev *uci_dev) +{ + struct mhi_device *mhi_dev = uci_dev->mhi_dev; + int nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); + size_t mtu = uci_dev->mtu; + void *buf; + struct uci_buf *uci_buf; + int ret = -EIO, i; + + for (i = 0; i < nr_trbs; i++) { + buf = kmalloc(mtu + sizeof(*uci_buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + uci_buf = buf + mtu; + uci_buf->data = buf; + + MSG_VERB("Allocated buf %d of %d size %ld\n", i, nr_trbs, mtu); + + ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf, mtu, +MHI_EOT); + if (ret) { + kfree(buf); +
[PATCH v1 4/4] mhi_bus: dev: uci: add user space interface driver
This module allows user space clients to transfer data between external modem and host using standard file operations. Signed-off-by: Sujeev Dias --- drivers/bus/mhi/devices/Kconfig | 9 + drivers/bus/mhi/devices/Makefile | 1 + drivers/bus/mhi/devices/mhi_uci.c | 662 ++ 3 files changed, 672 insertions(+) create mode 100644 drivers/bus/mhi/devices/mhi_uci.c diff --git a/drivers/bus/mhi/devices/Kconfig b/drivers/bus/mhi/devices/Kconfig index 40f964d..83b9673 100644 --- a/drivers/bus/mhi/devices/Kconfig +++ b/drivers/bus/mhi/devices/Kconfig @@ -7,4 +7,13 @@ config MHI_NETDEV MHI based net device driver for transferring IP traffic between host and modem. By enabling this driver, clients can transfer data using standard network interface. + +config MHI_UCI + tristate "MHI UCI" + depends on MHI_BUS + help + MHI based uci driver is for transferring data between host and + modem using standard file operations from user space. Open, read, + write, ioctl, and close operations are supported by this driver. + endmenu diff --git a/drivers/bus/mhi/devices/Makefile b/drivers/bus/mhi/devices/Makefile index ee12a64..300eed1 100644 --- a/drivers/bus/mhi/devices/Makefile +++ b/drivers/bus/mhi/devices/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_MHI_NETDEV) +=mhi_netdev.o +obj-$(CONFIG_MHI_UCI) +=mhi_uci.o diff --git a/drivers/bus/mhi/devices/mhi_uci.c b/drivers/bus/mhi/devices/mhi_uci.c new file mode 100644 index 000..11b7b1f --- /dev/null +++ b/drivers/bus/mhi/devices/mhi_uci.c @@ -0,0 +1,662 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_NAME "mhi" +#define MHI_UCI_DRIVER_NAME "mhi_uci" + +struct uci_chan { + wait_queue_head_t wq; + spinlock_t lock; + struct list_head pending; /* user space waiting to read */ + struct uci_buf *cur_buf; /* current buffer user space reading */ + size_t rx_size; +}; + +struct uci_buf { + void *data; + size_t len; + struct list_head node; +}; + +struct uci_dev { + struct list_head node; + dev_t devt; + struct device *dev; + struct mhi_device *mhi_dev; + const char *chan; + struct mutex mutex; /* sync open and close */ + struct uci_chan ul_chan; + struct uci_chan dl_chan; + size_t mtu; + int ref_count; + bool enabled; +}; + +struct mhi_uci_drv { + struct list_head head; + struct mutex lock; + struct class *class; + int major; + dev_t dev_t; +}; + +enum MHI_DEBUG_LEVEL msg_lvl = MHI_MSG_LVL_ERROR; + +#ifdef CONFIG_MHI_DEBUG + +#define MSG_VERB(fmt, ...) do { \ + if (msg_lvl <= MHI_MSG_LVL_VERBOSE) \ + pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#else + +#define MSG_VERB(fmt, ...) + +#endif + +#define MSG_LOG(fmt, ...) do { \ + if (msg_lvl <= MHI_MSG_LVL_INFO) \ + pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#define MSG_ERR(fmt, ...) do { \ + if (msg_lvl <= MHI_MSG_LVL_ERROR) \ + pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \ + } while (0) + +#define MAX_UCI_DEVICES (64) + +static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES); +static struct mhi_uci_drv mhi_uci_drv; + +static int mhi_queue_inbound(struct uci_dev *uci_dev) +{ + struct mhi_device *mhi_dev = uci_dev->mhi_dev; + int nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); + size_t mtu = uci_dev->mtu; + void *buf; + struct uci_buf *uci_buf; + int ret = -EIO, i; + + for (i = 0; i < nr_trbs; i++) { + buf = kmalloc(mtu + sizeof(*uci_buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + uci_buf = buf + mtu; + uci_buf->data = buf; + + MSG_VERB("Allocated buf %d of %d size %ld\n", i, nr_trbs, mtu); + + ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf, mtu, +MHI_EOT); + if (ret) { + kfree(buf); +