Skip to contentSkip to conversation

MHI initial design review

PATCH In review Sujeev Dias 8 participants 47 messages Apr 27, 2018 – Jun 12, 2019

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

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

#1 lore raw

PATCH 1/4 mhi_bus: core: Add support for MHI host interface

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.

---
 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(+)
 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_boot.c
 create mode 100644 drivers/bus/mhi/core/mhi_dtr.c
 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 drivers/bus/mhi/core/mhi_pm.c
 create mode 100644 include/linux/mhi.h
Documentation/00-INDEX +2 -0
index 708dc4c..44e2c6b 100644
@@ -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/
Documentation/devicetree/bindings/bus/mhi.txt new file +141 -0

141 lines not on this page · raw message

Documentation/mhi.txt new file +235 -0

235 lines not on this page · raw message

drivers/bus/Kconfig +17 -0
index d1c0b60..e15d56d 100644
@@ -171,6 +171,23 @@ config DA8XX_MSTPRI
 	  configuration. Allows to adjust the priorities of all master
 	  peripherals.
 
+config MHI_BUS
+	tristate "Modem Host Interface"
+	help
+	  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.
+	  Enabling this module will allow host to communicate with external
+	  devices that support MHI protocol.
+
+config MHI_DEBUG
+	 bool "MHI debug support"
+	 depends on MHI_BUS
+	 help
+	   Say yes here to enable debugging support in the MHI transport
+	   and individual MHI client drivers. This option will impact
+	   throughput as individual MHI packets and state transitions
+	   will be logged.
+
 source "drivers/bus/fsl-mc/Kconfig"
 
 endmenu
drivers/bus/Makefile +1 -0
index b8f036c..8fc0b3b 100644
@@ -31,3 +31,4 @@ obj-$(CONFIG_UNIPHIER_SYSTEM_BUS)	+= uniphier-system-bus.o
 obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o
 
 obj-$(CONFIG_DA8XX_MSTPRI)	+= da8xx-mstpri.o
+obj-$(CONFIG_MHI_BUS) += mhi/
drivers/bus/mhi/Makefile new file +8 -0
new file mode 100644
index 0000000..9f8f3ac
@@ -0,0 +1,8 @@
+#
+# Makefile for the MHI stack
+#
+
+# core layer
+obj-y += core/
+#obj-y += controllers/
+#obj-y += devices/
drivers/bus/mhi/core/Makefile new file +1 -0
new file mode 100644
index 0000000..a743fbf
@@ -0,0 +1 @@
+obj-$(CONFIG_MHI_BUS) +=mhi_init.o mhi_main.o mhi_pm.o mhi_boot.o mhi_dtr.o
drivers/bus/mhi/core/mhi_boot.c new file +593 -0

593 lines not on this page · raw message

drivers/bus/mhi/core/mhi_dtr.c new file +177 -0

177 lines not on this page · raw message

drivers/bus/mhi/core/mhi_init.c new file +1290 -0

1,290 lines not on this page · raw message

drivers/bus/mhi/core/mhi_internal.h new file +732 -0

520 lines not on this page · raw message

drivers/bus/mhi/core/mhi_main.c new file +1476 -0

1,476 lines not on this page · raw message

drivers/bus/mhi/core/mhi_pm.c new file +1177 -0

1,177 lines not on this page · raw message

include/linux/mhi.h new file +694 -0

694 lines not on this page · raw message

include/linux/mod_devicetable.h +11 -0
index 7d361be..1e11e30 100644

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

Part of the diff is not shown here. View the raw message.

#2 lore raw

Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface

Quoted 6 lines · Sujeev Dias

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.

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 :)

Quoted 9 lines
---
 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 ++++++++++
Quoted 8 lines
 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:

Quoted 1 line

+#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.

Quoted 17 lines
include/linux/mhi.h new file +17 -0
+
+#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)
+

include/linux/mhi.h line 692

Quoted 10 lines
include/linux/mhi.h new file +10 -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 :)

thanks,

greg k-h

#3 lore raw

Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface

Thanks for quick feedback

Quoted 6 lines · Greg Kroah-Hartman
Quoted 5 lines · Sujeev Dias

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.

Quoted 6 lines
Quoted 1 line

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.

Quoted 28 lines
Quoted 9 lines
---
  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 ++++++++++
Quoted 8 lines
  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.

Quoted 7 lines

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

Quoted 3 lines
Quoted 1 line

+#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...

Quoted 33 lines
Quoted 17 lines
include/linux/mhi.h new file +17 -0
+
+#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)
+

include/linux/mhi.h line 692

Quoted 10 lines
include/linux/mhi.h new file +10 -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.

Quoted 1 line

And I doubt you want to make such a statement :)

well :).. I will remove them in next revision.

Quoted 7 lines

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Thanks
Sujeev

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#4 lore raw

Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface

Quoted 10 lines · Sujeev Dias

Thanks for quick feedback

Quoted 6 lines · Greg Kroah-Hartman
Quoted 5 lines · Sujeev Dias

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.

Quoted 8 lines
Quoted 6 lines
Quoted 1 line

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.

Thank you.

Quoted 4 lines

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.

That's exactly what dev_dbg() does today. So please use it.

Quoted 1 line

I will look into tracepoints...

Or that, if you want them, they can be useful on data paths.

thanks,

greg k-h

#5 lore raw

Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface

In reply to Sujeev Dias
Quoted 4 lines · Sujeev Dias
drivers/bus/mhi/core/mhi_boot.c new file +1 -0
@@ -0,0 +1,593 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.

drivers/bus/mhi/core/mhi_boot.c line 11

Quoted 10 lines
drivers/bus/mhi/core/mhi_boot.c new file +10 -0
+ *
+ * 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.
+ */

Also, please use the proper SPDX headers on all new files, and do not put the "boiler-plate" license crud here either.

thanks,

greg k-h

#6 lore raw

Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface

In reply to Sujeev Dias
Quoted 58 lines · Sujeev Dias
Documentation/devicetree/bindings/bus/mhi.txt new file +52 -0
new file mode 100644
index 0000000..ea1b620
@@ -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: <u32>
+  Definition: Maximum number of channels supported by this controller
+
+- mhi,chan-cfg
+  Usage: required
+  Value type: Array of <u32>
+  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.

Documentation/devicetree/bindings/bus/mhi.txt line 62

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+               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 <string>
+  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.

Documentation/devicetree/bindings/bus/mhi.txt line 92

Quoted 4 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +4 -0
+- mhi,fw-name
+  Usage: optional
+  Value type: <string>
+  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.

Quoted 7 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +7 -0
+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.

Documentation/devicetree/bindings/bus/mhi.txt line 83

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+
+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?

Documentation/devicetree/bindings/bus/mhi.txt line 93

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+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 = &mhi_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 ;-)

Documentation/devicetree/bindings/bus/mhi.txt line 94

Quoted 1 line
Documentation/devicetree/bindings/bus/mhi.txt new file +1 -0
+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.

Quoted 5 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +5 -0
+void mhi_init_debugfs(struct mhi_controller *mhi_cntrl)
+{
+       struct dentry *dentry;
+       char node[32];
+

Documentation/devicetree/bindings/bus/mhi.txt line 109

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+       if (!mhi_cntrl->parent)
+               return;
+
+       snprintf(node, sizeof(node), "%04x_%02u:%02u.%02u",
+                mhi_cntrl->dev_id, mhi_cntrl->domain, mhi_cntrl->bus,
+                mhi_cntrl->slot);
+
+       dentry = debugfs_create_dir(node, mhi_cntrl->parent);
+       if (IS_ERR_OR_NULL(dentry))
+               return;

Using IS_ERR_OR_NULL() just means that you have misunderstood the interface, you want IS_ERR() here.

Documentation/devicetree/bindings/bus/mhi.txt line 112

Quoted 3 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +3 -0
+#if defined(CONFIG_OF)
+static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl,
+                          struct device_node *of_node)

Why the #ifdef? Do you ever build this on architectures that don't support CONFIG_OF yet? Which ones?

Documentation/devicetree/bindings/bus/mhi.txt line 123

Quoted 11 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +11 -0
+struct __packed mhi_event_ctxt {
+       u32 reserved : 8;
+       u32 intmodc : 8;
+       u32 intmodt : 16;
+       u32 ertype;
+       u32 msivec;
+       u64 rbase;
+       u64 rlen;
+       u64 rp;
+       u64 wp;
+};

I would generally only mark those members as __packed that don't already have natural alignment, such as

struct mhi_event_ctxt {
       u32 reserved : 8;
       u32 intmodc : 8;
       u32 intmodt : 16;
       u32 ertype;
       u32 msivec;
       u64 rbase __packed __aligned(4);
       u64 rlen__packed __aligned(4);
       u64 rp __packed __aligned(4);
       u64 wp__packed __aligned(4);
};

This clarifies where the hardware designers screwed up without forcing bytewise access to the structures.

Quoted 6 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +6 -0
+
+#ifdef CONFIG_MHI_DEBUG
+
+#define MHI_ASSERT(cond, msg) do { \
+       if (cond) \
+               panic(msg); \

Documentation/devicetree/bindings/bus/mhi.txt line 139

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+} while (0)
+
+#else
+
+#define MHI_ASSERT(cond, msg) do { \
+       if (cond) { \
+               MHI_ERR(msg); \
+               WARN_ON(cond); \
+       } \
+} while (0)

Remove these.

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 6 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +6 -0
+struct mhi_controller {
+       struct list_head node;
+
+       /* device node for iommu ops */
+       struct device *dev;
+       struct device_node *of_node;

Hmm, shouldn't the mhi_controller itself be a device that is a child of ->dev? It feels like

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+       /* mmio base */
+       void __iomem *regs;
+       void __iomem *bhi;
+       void __iomem *wake_db;
+
+       /* device topology */
+       u32 dev_id;
+       u32 domain;
+       u32 bus;
+       u32 slot;

These are even stranger. This looks PCI specific, but if you have a pci_dev then you know all of them while for the case you don't have a pci_dev, they don't make sense.

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 11 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +11 -0
+       /* kernel log level */
+       enum MHI_DEBUG_LEVEL klog_lvl;
+
+       /* private log level controller driver to set */
+       enum MHI_DEBUG_LEVEL log_lvl;
+
+       /* controller specific data */
+       void *priv_data;
+       void *log_buf;
+       struct dentry *dentry;
+       struct dentry *parent;

All the debugfs stuff is a bit worrying. It seems so pervasive in the driver that it's hard to tell if any of it is actually used for more than just debugging. It might be better to split that out of the series and add back the debug files one at a time in separate patches that each explain why the files are still required. If you have successfully debugged a problem with one
file, it may have seemed useful but maybe it's not needed for any future bugs.

You might also be able to get more value out of tracepoints than debugfs files.

Quoted 6 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +6 -0
+};
+
+/**
+ * struct mhi_device - mhi device structure associated bind to channel
+ * @dev: Device associated with the channels
+ * @mtu: Maximum # of bytes controller support

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+ * @ul_chan_id: MHI channel id for UL transfer
+ * @dl_chan_id: MHI channel id for DL transfer
+ * @priv: Driver private data
+ */
+struct mhi_device {
+       struct device dev;
+       u32 dev_id;
+       u32 domain;
+       u32 bus;
+       u32 slot;

Again, shouldn't the pci stuff be part of the parent or grandparent device?

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 2 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +2 -0
+
+#if defined(CONFIG_MHI_BUS)

In what situation would you include this header without enabling CONFIG_MHI_BUS?

Quoted 19 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +19 -0
+
+#ifdef CONFIG_MHI_DEBUG
+
+#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)
+

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -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)
+

Again, these all should be removed. Just use dev_err() etc.

Quoted 8 lines
include/linux/mod_devicetable.h +0 -0
index 7d361be..1e11e30 100644
@@ -734,4 +734,15 @@ struct tb_service_id {
 #define TBSVC_MATCH_PROTOCOL_VERSION   0x0004
 #define TBSVC_MATCH_PROTOCOL_REVISION  0x0008
 

include/linux/mod_devicetable.h struct tb_service_id { · line 746

Quoted 10 lines
include/linux/mod_devicetable.h +10 -0
+
+/**
+ * struct mhi_device_id - MHI device identification
+ * @chan: MHI channel name
+ * @driver_data: driver data;
+ */
+struct mhi_device_id {
+       const char *chan;
+       kernel_ulong_t driver_data;
+};

I think you have to use a fixed-length string here, otherwise module autoloading cannot work.

Arnd

#7 lore raw

Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface

Quoted 196 lines · Arnd Bergmann
Quoted 58 lines · Sujeev Dias
Documentation/devicetree/bindings/bus/mhi.txt new file +52 -0
new file mode 100644
index 0000000..ea1b620
@@ -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: <u32>
+  Definition: Maximum number of channels supported by this controller
+
+- mhi,chan-cfg
+  Usage: required
+  Value type: Array of <u32>
+  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.

Documentation/devicetree/bindings/bus/mhi.txt line 62

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+               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 <string>
+  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.

Documentation/devicetree/bindings/bus/mhi.txt line 92

Quoted 4 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +4 -0
+- mhi,fw-name
+  Usage: optional
+  Value type: <string>
+  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.

Quoted 7 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +7 -0
+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.

Documentation/devicetree/bindings/bus/mhi.txt line 83

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+
+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?

Documentation/devicetree/bindings/bus/mhi.txt line 93

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+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 = &mhi_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 ;-)

Documentation/devicetree/bindings/bus/mhi.txt line 94

Quoted 1 line
Documentation/devicetree/bindings/bus/mhi.txt new file +1 -0
+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.

Quoted 5 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +5 -0
+void mhi_init_debugfs(struct mhi_controller *mhi_cntrl)
+{
+       struct dentry *dentry;
+       char node[32];
+

Documentation/devicetree/bindings/bus/mhi.txt line 109

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+       if (!mhi_cntrl->parent)
+               return;
+
+       snprintf(node, sizeof(node), "%04x_%02u:%02u.%02u",
+                mhi_cntrl->dev_id, mhi_cntrl->domain, mhi_cntrl->bus,
+                mhi_cntrl->slot);
+
+       dentry = debugfs_create_dir(node, mhi_cntrl->parent);
+       if (IS_ERR_OR_NULL(dentry))
+               return;

Using IS_ERR_OR_NULL() just means that you have misunderstood the interface, you want IS_ERR() here.

Documentation/devicetree/bindings/bus/mhi.txt line 112

Quoted 3 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +3 -0
+#if defined(CONFIG_OF)
+static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl,
+                          struct device_node *of_node)

Why the #ifdef? Do you ever build this on architectures that don't support CONFIG_OF yet? Which ones?

Documentation/devicetree/bindings/bus/mhi.txt line 123

Quoted 11 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +11 -0
+struct __packed mhi_event_ctxt {
+       u32 reserved : 8;
+       u32 intmodc : 8;
+       u32 intmodt : 16;
+       u32 ertype;
+       u32 msivec;
+       u64 rbase;
+       u64 rlen;
+       u64 rp;
+       u64 wp;
+};

I would generally only mark those members as __packed that don't already have natural alignment, such as

struct mhi_event_ctxt {
        u32 reserved : 8;
        u32 intmodc : 8;
        u32 intmodt : 16;
        u32 ertype;
        u32 msivec;
        u64 rbase __packed __aligned(4);
        u64 rlen__packed __aligned(4);
        u64 rp __packed __aligned(4);
        u64 wp__packed __aligned(4);
};

This clarifies where the hardware designers screwed up without forcing bytewise access to the structures.

Quoted 6 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +6 -0
+
+#ifdef CONFIG_MHI_DEBUG
+
+#define MHI_ASSERT(cond, msg) do { \
+       if (cond) \
+               panic(msg); \

Documentation/devicetree/bindings/bus/mhi.txt line 139

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+} while (0)
+
+#else
+
+#define MHI_ASSERT(cond, msg) do { \
+       if (cond) { \
+               MHI_ERR(msg); \
+               WARN_ON(cond); \
+       } \
+} while (0)

Remove these.

Quoted 8 lines

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 6 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +6 -0
+struct mhi_controller {
+       struct list_head node;
+
+       /* device node for iommu ops */
+       struct device *dev;
+       struct device_node *of_node;

Hmm, shouldn't the mhi_controller itself be a device that is a child of ->dev? It feels like

Originally I did thought about it but I did not see any value of doing that. Not only that, I would need the parent device for all memory allocation and mapping since children device doesn't inherit parent iommu settings.

Quoted 10 lines

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+       /* mmio base */
+       void __iomem *regs;
+       void __iomem *bhi;
+       void __iomem *wake_db;
+
+       /* device topology */
+       u32 dev_id;
+       u32 domain;
+       u32 bus;
+       u32 slot;
Quoted 3 lines

These are even stranger. This looks PCI specific, but if you have a pci_dev then you know all of them while for the case you don't have a pci_dev, they don't make sense.

From MHI bus point of view, this is a memory mapped device. Not technically tied to a pci device. I would like to keep that abstraction.

Quoted 33 lines

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 11 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +11 -0
+       /* kernel log level */
+       enum MHI_DEBUG_LEVEL klog_lvl;
+
+       /* private log level controller driver to set */
+       enum MHI_DEBUG_LEVEL log_lvl;
+
+       /* controller specific data */
+       void *priv_data;
+       void *log_buf;
+       struct dentry *dentry;
+       struct dentry *parent;

All the debugfs stuff is a bit worrying. It seems so pervasive in the driver that it's hard to tell if any of it is actually used for more than just debugging. It might be better to split that out of the series and add back the debug files one at a time in separate patches that each explain why the files are still required. If you have successfully debugged a problem with one
file, it may have seemed useful but maybe it's not needed for any future bugs.

You might also be able to get more value out of tracepoints than debugfs files.

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+};
+
+/**
+ * struct mhi_device - mhi device structure associated bind to channel
+ * @dev: Device associated with the channels
+ * @mtu: Maximum # of bytes controller support
+ * @ul_chan_id: MHI channel id for UL transfer
+ * @dl_chan_id: MHI channel id for DL transfer
+ * @priv: Driver private data
+ */
Quoted 8 lines

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 6 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +6 -0
+struct mhi_device {
+       struct device dev;
+       u32 dev_id;
+       u32 domain;
+       u32 bus;
+       u32 slot;

Again, shouldn't the pci stuff be part of the parent or grandparent device?

This is for clients, they are absolutely not pcie aware at all. To them this is just a unique way to identify the physical device.

Quoted 57 lines

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 2 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +2 -0
+
+#if defined(CONFIG_MHI_BUS)

In what situation would you include this header without enabling CONFIG_MHI_BUS?

Quoted 19 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +19 -0
+
+#ifdef CONFIG_MHI_DEBUG
+
+#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)
+

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -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)
+

Again, these all should be removed. Just use dev_err() etc.

Quoted 8 lines
include/linux/mod_devicetable.h +0 -0
index 7d361be..1e11e30 100644
@@ -734,4 +734,15 @@ struct tb_service_id {
  #define TBSVC_MATCH_PROTOCOL_VERSION   0x0004
  #define TBSVC_MATCH_PROTOCOL_REVISION  0x0008
 

include/linux/mod_devicetable.h struct tb_service_id { · line 746

Quoted 10 lines
include/linux/mod_devicetable.h +10 -0
+
+/**
+ * struct mhi_device_id - MHI device identification
+ * @chan: MHI channel name
+ * @driver_data: driver data;
+ */
+struct mhi_device_id {
+       const char *chan;
+       kernel_ulong_t driver_data;
+};

I think you have to use a fixed-length string here, otherwise module autoloading cannot work.

Quoted 5 lines

Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Thank you
Sujeev

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#8 lore raw

Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface

In reply to Sujeev Dias
Thank you for the patch! Yet something to improve:

Hi Sujeev,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.17-rc2 next-20180426]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Sujeev-Dias/mhi_bus-core-Add-support-for-MHI-host-interface/20180428-065959
config: i386-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0 reproduce:

        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

In file included from drivers/bus/mhi/core/mhi_init.c:23:0:

>> include/linux/mhi.h:658:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    static inlint int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl)
                  ^~~
>> drivers/bus/mhi/core/mhi_init.c:608:5: error: redefinition of 'mhi_device_configure'
    int mhi_device_configure(struct mhi_device *mhi_dev,
        ^~~~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_init.c:23:0:
   include/linux/mhi.h:545:19: note: previous definition of 'mhi_device_configure' was here
    static inline int mhi_device_configure(struct mhi_device *mhi_div,
                      ^~~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_init.c:914:5: error: redefinition of 'of_register_mhi_controller'
    int of_register_mhi_controller(struct mhi_controller *mhi_cntrl)
        ^~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_init.c:23:0:
   include/linux/mhi.h:599:19: note: previous definition of 'of_register_mhi_controller' was here
    static inline int of_register_mhi_controller(struct mhi_controller *mhi_cntrl)
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_init.c:995:6: error: redefinition of 'mhi_unregister_mhi_controller'
    void mhi_unregister_mhi_controller(struct mhi_controller *mhi_cntrl)
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_init.c:23:0:
   include/linux/mhi.h:604:20: note: previous definition of 'mhi_unregister_mhi_controller' was here
    static inline void mhi_unregister_mhi_controller(
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_init.c:1015:24: error: redefinition of 'mhi_alloc_controller'
    struct mhi_controller *mhi_alloc_controller(size_t size)
                           ^~~~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_init.c:23:0:
   include/linux/mhi.h:594:38: note: previous definition of 'mhi_alloc_controller' was here
    static inline struct mhi_controller *mhi_alloc_controller(size_t size)
                                         ^~~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_init.c:1028:5: error: redefinition of 'mhi_prepare_for_power_up'
    int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl)
        ^~~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_init.c:23:0:
   include/linux/mhi.h:617:19: note: previous definition of 'mhi_prepare_for_power_up' was here
    static inline int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl)
                      ^~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_init.c:1070:6: error: redefinition of 'mhi_unprepare_after_power_down'
    void mhi_unprepare_after_power_down(struct mhi_controller *mhi_cntrl)
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_init.c:23:0:
   include/linux/mhi.h:637:20: note: previous definition of 'mhi_unprepare_after_power_down' was here
    static inline void mhi_unprepare_after_power_down(
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_init.c:1225:5: error: redefinition of 'mhi_driver_register'
    int mhi_driver_register(struct mhi_driver *mhi_drv)
        ^~~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_init.c:23:0:
   include/linux/mhi.h:536:19: note: previous definition of 'mhi_driver_register' was here
    static inline int mhi_driver_register(struct mhi_driver *mhi_drv)
                      ^~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_init.c:1239:6: error: redefinition of 'mhi_driver_unregister'

void mhi_driver_unregister(struct mhi_driver *mhi_drv)
^~~~~~~~~~~~~~~~~~~~~
In file included from drivers/bus/mhi/core/mhi_init.c:23:0:
include/linux/mhi.h:541:20: note: previous definition of 'mhi_driver_unregister' was here
static inline void mhi_driver_unregister(struct mhi_driver *mhi_drv)
^~~~~~~~~~~~~~~~~~~~~
--
In file included from drivers/bus/mhi/core/mhi_main.c:23:0:

>> include/linux/mhi.h:658:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    static inlint int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl)
                  ^~~
   drivers/bus/mhi/core/mhi_main.c: In function 'mhi_debugfs_mhi_event_show':
>> drivers/bus/mhi/core/mhi_main.c:1335:44: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 5 has type 'dma_addr_t {aka unsigned int}' [-Wformat=]
           " rp:0x%llx wp:0x%llx local_rp:0x%llx db:0x%llx\n",
                                            ~~~^
                                            %x
   drivers/bus/mhi/core/mhi_main.c:1337:8:
           mhi_to_physical(ring, ring->rp),
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      
   drivers/bus/mhi/core/mhi_main.c:1335:54: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 6 has type 'dma_addr_t {aka unsigned int}' [-Wformat=]
           " rp:0x%llx wp:0x%llx local_rp:0x%llx db:0x%llx\n",
                                                      ~~~^
                                                      %x
   drivers/bus/mhi/core/mhi_main.c:1338:8:
           mhi_event->db_cfg.db_val);
           ~~~~~~~~~~~~~~~~~~~~~~~~                       
   drivers/bus/mhi/core/mhi_main.c: In function 'mhi_debugfs_mhi_chan_show':
   drivers/bus/mhi/core/mhi_main.c:1368:57: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 6 has type 'dma_addr_t {aka unsigned int}' [-Wformat=]
           " base:0x%llx len:0x%llx wp:0x%llx local_rp:0x%llx local_wp:0x%llx db:0x%llx\n",
                                                         ~~~^
                                                         %x
   drivers/bus/mhi/core/mhi_main.c:1371:8:
           mhi_to_physical(ring, ring->rp),
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                   
   drivers/bus/mhi/core/mhi_main.c:1368:73: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 7 has type 'dma_addr_t {aka unsigned int}' [-Wformat=]
           " base:0x%llx len:0x%llx wp:0x%llx local_rp:0x%llx local_wp:0x%llx db:0x%llx\n",
                                                                         ~~~^
                                                                         %x
   drivers/bus/mhi/core/mhi_main.c:1372:8:
           mhi_to_physical(ring, ring->wp),
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                   
   drivers/bus/mhi/core/mhi_main.c:1368:83: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 8 has type 'dma_addr_t {aka unsigned int}' [-Wformat=]
           " base:0x%llx len:0x%llx wp:0x%llx local_rp:0x%llx local_wp:0x%llx db:0x%llx\n",
                                                                                   ~~~^
                                                                                   %x
   drivers/bus/mhi/core/mhi_main.c:1373:8:
           mhi_chan->db_cfg.db_val);
           ~~~~~~~~~~~~~~~~~~~~~~~                                                     
   drivers/bus/mhi/core/mhi_main.c: At top level:
>> drivers/bus/mhi/core/mhi_main.c:1381:5: error: redefinition of 'mhi_prepare_for_transfer'
    int mhi_prepare_for_transfer(struct mhi_device *mhi_dev)
        ^~~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_main.c:23:0:
   include/linux/mhi.h:566:19: note: previous definition of 'mhi_prepare_for_transfer' was here
    static inline int mhi_prepare_for_transfer(struct mhi_device *mhi_dev)
                      ^~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_main.c:1417:6: error: redefinition of 'mhi_unprepare_from_transfer'
    void mhi_unprepare_from_transfer(struct mhi_device *mhi_dev)
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_main.c:23:0:
   include/linux/mhi.h:571:20: note: previous definition of 'mhi_unprepare_from_transfer' was here
    static inline void mhi_unprepare_from_transfer(struct mhi_device *mhi_dev)
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_main.c:1434:5: error: redefinition of 'mhi_get_no_free_descriptors'
    int mhi_get_no_free_descriptors(struct mhi_device *mhi_dev,
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_main.c:23:0:
   include/linux/mhi.h:576:19: note: previous definition of 'mhi_get_no_free_descriptors' was here
    static inline int mhi_get_no_free_descriptors(struct mhi_device *mhi_dev,
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_main.c:1446:24: error: redefinition of 'mhi_bdf_to_controller'
    struct mhi_controller *mhi_bdf_to_controller(u32 domain,
                           ^~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_main.c:23:0:
   include/linux/mhi.h:609:38: note: previous definition of 'mhi_bdf_to_controller' was here
    static inline struct mhi_controller *mhi_bdf_to_controller(u32 domain,
                                         ^~~~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_main.c:1462:5: error: redefinition of 'mhi_poll'

int mhi_poll(struct mhi_device *mhi_dev,
^~~~~~~~
In file included from drivers/bus/mhi/core/mhi_main.c:23:0:
include/linux/mhi.h:582:19: note: previous definition of 'mhi_poll' was here
static inline int mhi_poll(struct mhi_device *mhi_dev, u32 budget)
^~~~~~~~
--
In file included from drivers/bus/mhi/core/mhi_pm.c:24:0:

>> include/linux/mhi.h:658:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    static inlint int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl)
                  ^~~
>> drivers/bus/mhi/core/mhi_pm.c:782:5: error: redefinition of 'mhi_async_power_up'
    int mhi_async_power_up(struct mhi_controller *mhi_cntrl)
        ^~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_pm.c:24:0:
   include/linux/mhi.h:622:19: note: previous definition of 'mhi_async_power_up' was here
    static inline int mhi_async_power_up(struct mhi_controller *mhi_cntrl)
                      ^~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_pm.c:873:6: error: redefinition of 'mhi_power_down'
    void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful)
         ^~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_pm.c:24:0:
   include/linux/mhi.h:632:20: note: previous definition of 'mhi_power_down' was here
    static inline void mhi_power_down(struct mhi_controller *mhi_cntrl,
                       ^~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_pm.c:907:5: error: redefinition of 'mhi_sync_power_up'
    int mhi_sync_power_up(struct mhi_controller *mhi_cntrl)
        ^~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_pm.c:24:0:
   include/linux/mhi.h:627:19: note: previous definition of 'mhi_sync_power_up' was here
    static inline int mhi_sync_power_up(struct mhi_controller *mhi_cntrl)
                      ^~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_pm.c:923:5: error: redefinition of 'mhi_pm_suspend'
    int mhi_pm_suspend(struct mhi_controller *mhi_cntrl)
        ^~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_pm.c:24:0:
   include/linux/mhi.h:642:19: note: previous definition of 'mhi_pm_suspend' was here
    static inline int mhi_pm_suspend(struct mhi_controller *mhi_cntrl)
                      ^~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_pm.c:1012:5: error: redefinition of 'mhi_pm_resume'
    int mhi_pm_resume(struct mhi_controller *mhi_cntrl)
        ^~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_pm.c:24:0:
   include/linux/mhi.h:647:19: note: previous definition of 'mhi_pm_resume' was here
    static inline int mhi_pm_resume(struct mhi_controller *mhi_cntrl)
                      ^~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_pm.c:1097:6: error: redefinition of 'mhi_device_get'
    void mhi_device_get(struct mhi_device *mhi_dev)
         ^~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_pm.c:24:0:
   include/linux/mhi.h:553:20: note: previous definition of 'mhi_device_get' was here
    static inline void mhi_device_get(struct mhi_device *mhi_dev)
                       ^~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_pm.c:1108:5: error: redefinition of 'mhi_device_get_sync'
    int mhi_device_get_sync(struct mhi_device *mhi_dev)
        ^~~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_pm.c:24:0:
   include/linux/mhi.h:557:19: note: previous definition of 'mhi_device_get_sync' was here
    static inline int mhi_device_get_sync(struct mhi_device *mhi_dev)
                      ^~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/core/mhi_pm.c:1121:6: error: redefinition of 'mhi_device_put'

void mhi_device_put(struct mhi_device *mhi_dev)
^~~~~~~~~~~~~~
In file included from drivers/bus/mhi/core/mhi_pm.c:24:0:
include/linux/mhi.h:562:20: note: previous definition of 'mhi_device_put' was here
static inline void mhi_device_put(struct mhi_device *mhi_dev)
^~~~~~~~~~~~~~
--
In file included from drivers/bus/mhi/core/mhi_boot.c:26:0:

>> include/linux/mhi.h:658:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
    static inlint int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl)
                  ^~~
>> drivers/bus/mhi/core/mhi_boot.c:138:5: error: redefinition of 'mhi_download_rddm_img'
    int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic)
        ^~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/bus/mhi/core/mhi_boot.c:26:0:
   include/linux/mhi.h:652:19: note: previous definition of 'mhi_download_rddm_img' was here
    static inline int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl,
                      ^~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/printk.h:7:0,
                    from include/linux/kernel.h:14,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from include/linux/debugfs.h:15,
                    from drivers/bus/mhi/core/mhi_boot.c:13:
   drivers/bus/mhi/core/mhi_boot.c: In function 'mhi_download_rddm_img':
   include/linux/kern_levels.h:5:18: warning: format '%lx' expects argument of type 'long unsigned int', but argument 5 has type 'size_t {aka unsigned int}' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/kern_levels.h:14:19: note: in expansion of macro 'KERN_SOH'
    #define KERN_INFO KERN_SOH "6" /* informational */
                      ^~~~~~~~
   include/linux/printk.h:311:9: note: in expansion of macro 'KERN_INFO'
     printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
            ^~~~~~~~~
>> include/linux/mhi.h:680:4: note: in expansion of macro 'pr_info'
       pr_info("[I][%s] " fmt, __func__, ##__VA_ARGS__);\
       ^~~~~~~
>> drivers/bus/mhi/core/mhi_boot.c:196:2: note: in expansion of macro 'MHI_LOG'
     MHI_LOG("Upper:0x%x Lower:0x%x len:0x%lx sequence:%u\n",
     ^~~~~~~
   drivers/bus/mhi/core/mhi_boot.c:196:41: note: format string is defined here
     MHI_LOG("Upper:0x%x Lower:0x%x len:0x%lx sequence:%u\n",
                                          ~~^
                                          %x
   In file included from include/linux/printk.h:7:0,
                    from include/linux/kernel.h:14,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from include/linux/debugfs.h:15,
                    from drivers/bus/mhi/core/mhi_boot.c:13:
   drivers/bus/mhi/core/mhi_boot.c: In function 'mhi_fw_load_amss':
>> include/linux/kern_levels.h:5:18: warning: format '%lx' expects argument of type 'long unsigned int', but argument 5 has type 'size_t {aka const unsigned int}' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/kern_levels.h:14:19: note: in expansion of macro 'KERN_SOH'
    #define KERN_INFO KERN_SOH "6" /* informational */
                      ^~~~~~~~
   include/linux/printk.h:311:9: note: in expansion of macro 'KERN_INFO'
     printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
            ^~~~~~~~~
>> include/linux/mhi.h:680:4: note: in expansion of macro 'pr_info'
       pr_info("[I][%s] " fmt, __func__, ##__VA_ARGS__);\
       ^~~~~~~
   drivers/bus/mhi/core/mhi_boot.c:248:2: note: in expansion of macro 'MHI_LOG'
     MHI_LOG("Upper:0x%x Lower:0x%x len:0x%lx sequence:%u\n",
     ^~~~~~~
   drivers/bus/mhi/core/mhi_boot.c:248:41: note: format string is defined here
     MHI_LOG("Upper:0x%x Lower:0x%x len:0x%lx sequence:%u\n",
                                          ~~^
                                          %x
   In file included from include/linux/printk.h:7:0,
                    from include/linux/kernel.h:14,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from include/linux/debugfs.h:15,
                    from drivers/bus/mhi/core/mhi_boot.c:13:
   drivers/bus/mhi/core/mhi_boot.c: In function 'mhi_alloc_bhie_table':
   include/linux/kern_levels.h:5:18: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 4 has type 'dma_addr_t {aka unsigned int}' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/kern_levels.h:14:19: note: in expansion of macro 'KERN_SOH'
    #define KERN_INFO KERN_SOH "6" /* informational */
                      ^~~~~~~~
   include/linux/printk.h:311:9: note: in expansion of macro 'KERN_INFO'
     printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
            ^~~~~~~~~
>> include/linux/mhi.h:680:4: note: in expansion of macro 'pr_info'
       pr_info("[I][%s] " fmt, __func__, ##__VA_ARGS__);\
       ^~~~~~~
   drivers/bus/mhi/core/mhi_boot.c:403:3: note: in expansion of macro 'MHI_LOG'
      MHI_LOG("Entry:%d Address:0x%llx size:%lu\n", i,
      ^~~~~~~
   drivers/bus/mhi/core/mhi_boot.c:403:34: note: format string is defined here
      MHI_LOG("Entry:%d Address:0x%llx size:%lu\n", i,
                                  ~~~^
                                  %x
   In file included from include/linux/printk.h:7:0,
                    from include/linux/kernel.h:14,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from include/linux/debugfs.h:15,
                    from drivers/bus/mhi/core/mhi_boot.c:13:
   include/linux/kern_levels.h:5:18: warning: format '%lu' expects argument of type 'long unsigned int', but argument 5 has type 'size_t {aka unsigned int}' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/kern_levels.h:14:19: note: in expansion of macro 'KERN_SOH'
    #define KERN_INFO KERN_SOH "6" /* informational */
                      ^~~~~~~~
   include/linux/printk.h:311:9: note: in expansion of macro 'KERN_INFO'
     printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
            ^~~~~~~~~
>> include/linux/mhi.h:680:4: note: in expansion of macro 'pr_info'
       pr_info("[I][%s] " fmt, __func__, ##__VA_ARGS__);\
       ^~~~~~~
   drivers/bus/mhi/core/mhi_boot.c:403:3: note: in expansion of macro 'MHI_LOG'
      MHI_LOG("Entry:%d Address:0x%llx size:%lu\n", i,
      ^~~~~~~
   drivers/bus/mhi/core/mhi_boot.c:403:43: note: format string is defined here
      MHI_LOG("Entry:%d Address:0x%llx size:%lu\n", i,
                                            ~~^
                                            %u

..

vim +658 include/linux/mhi.h

657

 > 658	static inlint int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl)
   659	{
   660		return -EINVAL;
   661	}
   662	
   663	#endif
   664	
   665	#ifdef CONFIG_MHI_DEBUG
   666	
   667	#define MHI_VERB(fmt, ...) do { \
   668			if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_VERBOSE) \
   669				pr_debug("[D][%s] " fmt, __func__, ##__VA_ARGS__);\
   670	} while (0)
   671	
   672	#else
   673	
   674	#define MHI_VERB(fmt, ...)
   675	
   676	#endif
   677	
   678	#define MHI_LOG(fmt, ...) do {	\
   679			if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_INFO) \
 > 680				pr_info("[I][%s] " fmt, __func__, ##__VA_ARGS__);\

681 } while (0)
682

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#9 lore raw

Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface

In reply to Sujeev Dias
Thank you for the patch! Yet something to improve:

Hi Sujeev,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.17-rc2 next-20180426]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Sujeev-Dias/mhi_bus-core-Add-support-for-MHI-host-interface/20180428-065959
config: sparc64-allyesconfig (attached as .config)
compiler: sparc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=sparc64

All error/warnings (new ones prefixed by >>):

drivers/bus/mhi/core/mhi_dtr.c: In function 'mhi_ioctl':

>> drivers/bus/mhi/core/mhi_dtr.c:108:9: error: implicit declaration of function 'get_user'; did you mean 'get_super'? [-Werror=implicit-function-declaration]
      ret = get_user(tiocm, (u32 *)arg);
            ^~~~~~~~
            get_super
>> drivers/bus/mhi/core/mhi_dtr.c:108:7: warning: 'tiocm' may be used uninitialized in this function [-Wmaybe-uninitialized]
      ret = get_user(tiocm, (u32 *)arg);
      ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

cc1: some warnings being treated as errors

vim +108 drivers/bus/mhi/core/mhi_dtr.c

    90	
    91	long mhi_ioctl(struct mhi_device *mhi_dev, unsigned int cmd, unsigned long arg)
    92	{
    93		struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
    94		struct mhi_chan *mhi_chan = mhi_dev->ul_chan;
    95		int ret;
    96	
    97		/* ioctl not supported by this controller */
    98		if (!mhi_cntrl->dtr_dev)
    99			return -EIO;
   100	
   101		switch (cmd) {
   102		case TIOCMGET:
   103			return mhi_chan->tiocm;
   104		case TIOCMSET:
   105		{
   106			u32 tiocm;
   107	
 > 108			ret = get_user(tiocm, (u32 *)arg);

109 if (ret)
110 return ret;
111
112 return mhi_dtr_tiocmset(mhi_cntrl, mhi_chan, tiocm);
113 }
114 default:
115 break;
116 }
117
118 return -EINVAL;
119 }
120 EXPORT_SYMBOL(mhi_ioctl);
121

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#10 lore raw

Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface

In reply to Sujeev Dias

Hi!

Quoted 4 lines

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?

Documentation/mhi.txt line 211

Quoted 5 lines
Documentation/mhi.txt new file +5 -0
+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?
Pavel

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
#11 lore raw

Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface

Hi Pavel

Quoted 10 lines · Pavel Machek

Hi!

Quoted 4 lines

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.

Quoted 7 lines

Documentation/mhi.txt line 211

Quoted 5 lines
Documentation/mhi.txt new file +5 -0
+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.

Quoted 1 line

Pavel

Thanks
Sujeev

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
reviewer
#12 lore raw

Re: [PATCH v1 1/4] mhi_bus: core: Add support for MHI host interface

In reply to Sujeev Dias

Hi,

drivers/bus/Kconfig config DA8XX_MSTPRI · line 177

Quoted 12 lines · Sujeev Dias
drivers/bus/Kconfig +4 -0
index d1c0b60..e15d56d 100644
@@ -171,6 +171,23 @@ config DA8XX_MSTPRI
 	  configuration. Allows to adjust the priorities of all master
 	  peripherals.
 
+config MHI_BUS
+	tristate "Modem Host Interface"
+	help
+	  MHI Host Interface is a communication protocol to be used by the host

MHI (Modem Host Interface) is

drivers/bus/Kconfig config DA8XX_MSTPRI · line 178

Quoted 1 line
drivers/bus/Kconfig +1 -0
+	  to control and communcate with modem over a high speed peripheral bus.

communicate

Quoted 15 lines
drivers/bus/Kconfig +12 -0
+	  Enabling this module will allow host to communicate with external
+	  devices that support MHI protocol.
+
+config MHI_DEBUG
+	 bool "MHI debug support"
+	 depends on MHI_BUS
+	 help
+	   Say yes here to enable debugging support in the MHI transport
+	   and individual MHI client drivers. This option will impact
+	   throughput as individual MHI packets and state transitions
+	   will be logged.
+
 source "drivers/bus/fsl-mc/Kconfig"
 
 endmenu
Signature · 1 line
~Randy
#13 lore raw

PATCH 2/4 mhi_bus: controller: MHI support for QCOM modems

In reply to Sujeev Dias

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.

---
 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
Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +110 -0
new file mode 100644
index 0000000..c0f8d86
@@ -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: <string>
+  Definition: "qcom,mhi"
+
+- qcom,pci-dev-id
+  Usage: optional
+  Value type: <u32>
+  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: <u32>
+  Definition: PCIe root complex external modem connected to
+
+- qcom,pci-bus
+  Usage: required
+  Value type: <u32>
+  Definition: PCIe bus external modem connected to
+
+- qcom,pci-slot
+  Usage: required
+  Value type: <u32>
+  Definition: PCIe slot as assigned by pci framework to external modem
+
+- qcom,smmu-cfg
+  Usage: required
+  Value type: <u32>
+  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 <u64>
+  Definition: Pair of values describing iova start and stop address
+
+- qcom,msm-bus,name
+  Usage: required
+  Value type: <string>
+  Definition: string representing the bus scale client name to register
+
+- qcom,msm-bus,num-cases
+  Usage: required
+  Value type: <u32>
+  Definition: Must be set to two, MHI support two scales
+
+- qcom,msm-bus,num-paths
+  Usage: required
+  Value type: <u32>
+  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 <u32>
+  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: <string>
+  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 0x20000000 0x0 0x3fffffff>;
+	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 1200000000 650000000>;
+	<mhi bus configurations>
+};
drivers/bus/Kconfig +1 -0
index e15d56d..fb28002 100644
@@ -189,5 +189,6 @@ config MHI_DEBUG
 	   will be logged.
 
 source "drivers/bus/fsl-mc/Kconfig"
+source drivers/bus/mhi/controllers/Kconfig
 
 endmenu
drivers/bus/mhi/Makefile +1 -1
index 9f8f3ac..c6a2a91 100644
@@ -4,5 +4,5 @@
 
 # core layer
 obj-y += core/
-#obj-y += controllers/
+obj-y += controllers/
 #obj-y += devices/
drivers/bus/mhi/controllers/Kconfig new file +10 -0
new file mode 100644
index 0000000..e8a90b6
@@ -0,0 +1,10 @@
+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.
+
+endmenu
drivers/bus/mhi/controllers/Makefile new file +1 -0
new file mode 100644
index 0000000..292f696
@@ -0,0 +1 @@
+obj-$(CONFIG_MHI_QCOM) += mhi_qcom.o
drivers/bus/mhi/controllers/mhi_qcom.c new file +686 -0

686 lines not on this page · raw message

drivers/bus/mhi/controllers/mhi_qcom.h new file +85 -0

85 lines not on this page · raw message

Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#14 lore raw

Re: [PATCH v1 2/4] mhi_bus: controller: MHI support for QCOM modems

Quoted 21 lines · Sujeev Dias

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

Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +14 -0
+  Usage: required
+  Value type: <string>
+  Definition: "qcom,mhi"
+
+- qcom,pci-dev-id
+  Usage: optional
+  Value type: <u32>
+  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: <u32>
+  Definition: PCIe root complex external modem connected to

Documentation/devicetree/bindings/bus/mhi_qcom.txt line 36

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +10 -0
+
+- qcom,pci-bus
+  Usage: required
+  Value type: <u32>
+  Definition: PCIe bus external modem connected to
+
+- qcom,pci-slot
+  Usage: required
+  Value type: <u32>
+  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?

Quoted 5 lines

+- qcom,smmu-cfg

Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +4 -0
+  Usage: required
+  Value type: <u32>
+  Definition: Required SMMU configuration bitmask for PCIe bus.
+       BIT mask:

Documentation/devicetree/bindings/bus/mhi_qcom.txt line 52

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +10 -0
+       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 <u64>
+  Definition: Pair of values describing iova start and stop address

Why do you need these? Can't that be handled by the PCI layer?

Documentation/devicetree/bindings/bus/mhi_qcom.txt line 57

Quoted 4 lines

+- qcom,msm-bus,name

Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +3 -0
+  Usage: required
+  Value type: <string>
+  Definition: string representing the bus scale client name to register

This probably belongs into a separate binding for the bus scale driver, right?

Quoted 1 line

+static struct pci_driver mhi_pcie_driver;

Please try to reorder the symbols to avoid forward declarations.

Quoted 25 lines
drivers/bus/mhi/controllers/mhi_qcom.c new file +25 -0
+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",
+                                  &mhi_cntrl->dev_id);
+       if (ret)
+               mhi_cntrl->dev_id = PCI_ANY_ID;
+
+       ret = of_property_read_u32(of_node, "qcom,pci-domain",
+                                  &mhi_cntrl->domain);

drivers/bus/mhi/controllers/mhi_qcom.c line 568

Quoted 10 lines
drivers/bus/mhi/controllers/mhi_qcom.c new file +10 -0
+       if (ret)
+               goto error_probe;
+
+       ret = of_property_read_u32(of_node, "qcom,pci-bus", &mhi_cntrl->bus);
+       if (ret)
+               goto error_probe;
+
+       ret = of_property_read_u32(of_node, "qcom,pci-slot", &mhi_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?

Arnd

#15 lore raw

Re: [PATCH v1 2/4] mhi_bus: controller: MHI support for QCOM modems

Quoted 26 lines · Arnd Bergmann
Quoted 25 lines · Sujeev Dias

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

Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +19 -0
+  Usage: required
+  Value type: <string>
+  Definition: "qcom,mhi"
+
+- qcom,pci-dev-id
+  Usage: optional
+  Value type: <u32>
+  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: <u32>
+  Definition: PCIe root complex external modem connected to
+
+- qcom,pci-bus
+  Usage: required
+  Value type: <u32>
+  Definition: PCIe bus external modem connected to
Quoted 9 lines

Documentation/devicetree/bindings/bus/mhi_qcom.txt line 36

Quoted 5 lines
Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +5 -0
+
+- qcom,pci-slot
+  Usage: required
+  Value type: <u32>
+  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.

Quoted 15 lines
Quoted 5 lines

+- qcom,smmu-cfg

Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +4 -0
+  Usage: required
+  Value type: <u32>
+  Definition: Required SMMU configuration bitmask for PCIe bus.
+       BIT mask:

Documentation/devicetree/bindings/bus/mhi_qcom.txt line 52

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +10 -0
+       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 <u64>
+  Definition: Pair of values describing iova start and stop address
Quoted 2 lines

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

Quoted 6 lines

Documentation/devicetree/bindings/bus/mhi_qcom.txt line 57

Quoted 4 lines

+- qcom,msm-bus,name

Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +3 -0
+  Usage: required
+  Value type: <string>
+  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.

Quoted 33 lines
Quoted 1 line

+static struct pci_driver mhi_pcie_driver;

Please try to reorder the symbols to avoid forward declarations.

Quoted 30 lines
drivers/bus/mhi/controllers/mhi_qcom.c new file +30 -0
+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",
+                                  &mhi_cntrl->dev_id);
+       if (ret)
+               mhi_cntrl->dev_id = PCI_ANY_ID;
+
+       ret = of_property_read_u32(of_node, "qcom,pci-domain",
+                                  &mhi_cntrl->domain);
+       if (ret)
+               goto error_probe;
+
+       ret = of_property_read_u32(of_node, "qcom,pci-bus", &mhi_cntrl->bus);
+       if (ret)
Quoted 8 lines

drivers/bus/mhi/controllers/mhi_qcom.c line 568

Quoted 5 lines
drivers/bus/mhi/controllers/mhi_qcom.c new file +5 -0
+               goto error_probe;
+
+       ret = of_property_read_u32(of_node, "qcom,pci-slot", &mhi_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.

Quoted 6 lines

Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Thanks again
Sujeev

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#16 lore raw

Re: [PATCH v1 2/4] mhi_bus: controller: MHI support for QCOM modems

In reply to Sujeev Dias
Thank you for the patch! Yet something to improve:

Hi Sujeev,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.17-rc2 next-20180426]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Sujeev-Dias/mhi_bus-core-Add-support-for-MHI-host-interface/20180428-065959
config: alpha-allmodconfig (attached as .config)
compiler: alpha-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=alpha

All errors (new ones prefixed by >>):

In file included from drivers/bus/mhi/controllers/mhi_qcom.c:25:0:
include/linux/mhi.h:658:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
static inlint int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl)
^~~
drivers/bus/mhi/controllers/mhi_qcom.c: In function 'mhi_platform_probe':

>> drivers/bus/mhi/controllers/mhi_qcom.c:587:17: error: implicit declaration of function 'memblock_start_of_DRAM'; did you mean 'memblock_alloc'? [-Werror=implicit-function-declaration]
      addr_win[0] = memblock_start_of_DRAM();
                    ^~~~~~~~~~~~~~~~~~~~~~
                    memblock_alloc
>> drivers/bus/mhi/controllers/mhi_qcom.c:588:17: error: implicit declaration of function 'memblock_end_of_DRAM'; did you mean 'memblock_alloc'? [-Werror=implicit-function-declaration]
      addr_win[1] = memblock_end_of_DRAM();
                    ^~~~~~~~~~~~~~~~~~~~
                    memblock_alloc

At top level:
drivers/bus/mhi/controllers/mhi_qcom.c:238:12: warning: 'mhi_system_resume' defined but not used [-Wunused-function]
static int mhi_system_resume(struct device *dev)
^~~~~~~~~~~~~~~~~
drivers/bus/mhi/controllers/mhi_qcom.c:186:12: warning: 'mhi_runtime_idle' defined but not used [-Wunused-function]
static int mhi_runtime_idle(struct device *dev)
^~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors

vim +587 drivers/bus/mhi/controllers/mhi_qcom.c

533
534 static int mhi_platform_probe(struct platform_device *pdev)
535 {
536 struct mhi_controller *mhi_cntrl;
537 struct mhi_dev *mhi_dev;
538 struct device_node *of_node = pdev->dev.of_node;
539 u64 addr_win[2];
540 int ret;
541
542 if (!of_node)
543 return -ENODEV;
544
545 mhi_cntrl = mhi_alloc_controller(sizeof(*mhi_dev));
546 if (!mhi_cntrl)
547 return -ENOMEM;
548
549 mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
550
551 /* get pci bus topology for this node */
552 ret = of_property_read_u32(of_node, "qcom,pci-dev-id",
553 &mhi_cntrl->dev_id);
554 if (ret)
555 mhi_cntrl->dev_id = PCI_ANY_ID;
556
557 ret = of_property_read_u32(of_node, "qcom,pci-domain",
558 &mhi_cntrl->domain);
559 if (ret)
560 goto error_probe;
561
562 ret = of_property_read_u32(of_node, "qcom,pci-bus", &mhi_cntrl->bus);
563 if (ret)
564 goto error_probe;
565
566 ret = of_property_read_u32(of_node, "qcom,pci-slot", &mhi_cntrl->slot);
567 if (ret)
568 goto error_probe;
569
570 ret = of_property_read_u32(of_node, "qcom,smmu-cfg",
571 &mhi_dev->smmu_cfg);
572 if (ret)
573 goto error_probe;
574
575 /* if s1 translation enabled pull iova addr from dt */
576 if (mhi_dev->smmu_cfg & MHI_SMMU_ATTACH &&
577 !(mhi_dev->smmu_cfg & MHI_SMMU_S1_BYPASS)) {
578 ret = of_property_count_elems_of_size(of_node, "qcom,addr-win",
579 sizeof(addr_win));
580 if (ret != 1)
581 goto error_probe;
582 ret = of_property_read_u64_array(of_node, "qcom,addr-win",
583 addr_win, 2);
584 if (ret)
585 goto error_probe;
586 } else {

 > 587			addr_win[0] = memblock_start_of_DRAM();
 > 588			addr_win[1] = memblock_end_of_DRAM();

589 }
590
591 mhi_dev->iova_start = addr_win[0];
592 mhi_dev->iova_stop = addr_win[1];
593
594 /*
595 * if S1 is enabled, set MHI_CTRL start address to 0 so we can use low
596 * level mapping api to map buffers outside of smmu domain
597 */
598 if (mhi_dev->smmu_cfg & MHI_SMMU_ATTACH &&
599 !(mhi_dev->smmu_cfg & MHI_SMMU_S1_BYPASS))
600 mhi_cntrl->iova_start = 0;
601 else
602 mhi_cntrl->iova_start = addr_win[0];
603
604 mhi_cntrl->iova_stop = mhi_dev->iova_stop;
605 mhi_cntrl->of_node = of_node;
606
607 /* setup power management apis */
608 mhi_cntrl->status_cb = mhi_status_cb;
609 mhi_cntrl->runtime_get = mhi_runtime_get;
610 mhi_cntrl->runtime_put = mhi_runtime_put;
611 mhi_cntrl->link_status = mhi_link_status;
612
613 mhi_dev->pdev = pdev;
614
615 ret = mhi_arch_platform_init(mhi_dev);
616 if (ret)
617 goto error_probe;
618
619 ret = of_register_mhi_controller(mhi_cntrl);
620 if (ret)
621 goto error_register;
622
623 if (mhi_cntrl->parent)
624 debugfs_create_file("debug_mode", 0444, mhi_cntrl->parent,
625 mhi_cntrl, &debugfs_debug_ops);
626
627 return 0;
628
629 error_register:
630 mhi_arch_platform_deinit(mhi_dev);
631
632 error_probe:
633 mhi_free_controller(mhi_cntrl);
634
635 return -EINVAL;
636 };
637

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#17 lore raw

Re: [PATCH v1 2/4] mhi_bus: controller: MHI support for QCOM modems

In reply to Sujeev Dias
Thank you for the patch! Yet something to improve:

Hi Sujeev,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.17-rc2 next-20180426]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Sujeev-Dias/mhi_bus-core-Add-support-for-MHI-host-interface/20180428-065959
config: openrisc-allmodconfig (attached as .config)
compiler: or1k-linux-gcc (GCC) 6.0.0 20160327 (experimental)
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=openrisc

All errors (new ones prefixed by >>):

In file included from drivers/bus/mhi/controllers/mhi_qcom.c:25:0:
include/linux/mhi.h:658:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
static inlint int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl)
^~~
drivers/bus/mhi/controllers/mhi_qcom.c: In function 'mhi_deinit_pci_dev':

>> drivers/bus/mhi/controllers/mhi_qcom.c:46:2: error: implicit declaration of function 'pci_free_irq_vectors' [-Werror=implicit-function-declaration]
     pci_free_irq_vectors(pci_dev);
     ^~~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/controllers/mhi_qcom.c:51:2: error: implicit declaration of function 'pci_clear_master' [-Werror=implicit-function-declaration]
     pci_clear_master(pci_dev);
     ^~~~~~~~~~~~~~~~
>> drivers/bus/mhi/controllers/mhi_qcom.c:52:2: error: implicit declaration of function 'pci_release_region' [-Werror=implicit-function-declaration]
     pci_release_region(pci_dev, mhi_dev->resn);
     ^~~~~~~~~~~~~~~~~~
   drivers/bus/mhi/controllers/mhi_qcom.c: In function 'mhi_init_pci_dev':
>> drivers/bus/mhi/controllers/mhi_qcom.c:77:8: error: implicit declaration of function 'pci_request_region' [-Werror=implicit-function-declaration]
     ret = pci_request_region(pci_dev, mhi_dev->resn, "mhi");
           ^~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/controllers/mhi_qcom.c:93:8: error: implicit declaration of function 'pci_alloc_irq_vectors' [-Werror=implicit-function-declaration]
     ret = pci_alloc_irq_vectors(pci_dev, mhi_cntrl->msi_required,
           ^~~~~~~~~~~~~~~~~~~~~
>> drivers/bus/mhi/controllers/mhi_qcom.c:94:34: error: 'PCI_IRQ_MSI' undeclared (first use in this function)
            mhi_cntrl->msi_required, PCI_IRQ_MSI);
                                     ^~~~~~~~~~~
   drivers/bus/mhi/controllers/mhi_qcom.c:94:34: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/bus/mhi/controllers/mhi_qcom.c:109:23: error: implicit declaration of function 'pci_irq_vector' [-Werror=implicit-function-declaration]
      mhi_cntrl->irq[i] = pci_irq_vector(pci_dev, i);
                          ^~~~~~~~~~~~~~

At top level:
drivers/bus/mhi/controllers/mhi_qcom.c:238:12: warning: 'mhi_system_resume' defined but not used [-Wunused-function]
static int mhi_system_resume(struct device *dev)
^~~~~~~~~~~~~~~~~
drivers/bus/mhi/controllers/mhi_qcom.c:186:12: warning: 'mhi_runtime_idle' defined but not used [-Wunused-function]
static int mhi_runtime_idle(struct device *dev)
^~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors

vim +/pci_free_irq_vectors +46 drivers/bus/mhi/controllers/mhi_qcom.c

  > 25	#include <linux/mhi.h>
    26	#include "mhi_qcom.h"
    27	
    28	static struct pci_device_id mhi_pcie_device_id[] = {
    29		{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0300)},
    30		{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0301)},
    31		{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0302)},
    32		{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0303)},
    33		{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0304)},
    34		{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0305)},
    35		{PCI_DEVICE(MHI_PCIE_VENDOR_ID, MHI_PCIE_DEBUG_ID)},
    36		{0},
    37	};
    38	
    39	static struct pci_driver mhi_pcie_driver;
    40	
    41	void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl)
    42	{
    43		struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
    44		struct pci_dev *pci_dev = mhi_dev->pci_dev;
    45	
  > 46		pci_free_irq_vectors(pci_dev);
    47		kfree(mhi_cntrl->irq);
    48		mhi_cntrl->irq = NULL;
    49		iounmap(mhi_cntrl->regs);
    50		mhi_cntrl->regs = NULL;
  > 51		pci_clear_master(pci_dev);
  > 52		pci_release_region(pci_dev, mhi_dev->resn);
    53		pci_disable_device(pci_dev);
    54	}
    55	
    56	static int mhi_init_pci_dev(struct mhi_controller *mhi_cntrl)
    57	{
    58		struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
    59		struct pci_dev *pci_dev = mhi_dev->pci_dev;
    60		int ret;
    61		resource_size_t start, len;
    62		int i;
    63	
    64		mhi_dev->resn = MHI_PCI_BAR_NUM;
    65		ret = pci_assign_resource(pci_dev, mhi_dev->resn);
    66		if (ret) {
    67			MHI_ERR("Error assign pci resources, ret:%d\n", ret);
    68			return ret;
    69		}
    70	
    71		ret = pci_enable_device(pci_dev);
    72		if (ret) {
    73			MHI_ERR("Error enabling device, ret:%d\n", ret);
    74			goto error_enable_device;
    75		}
    76	
  > 77		ret = pci_request_region(pci_dev, mhi_dev->resn, "mhi");
    78		if (ret) {
    79			MHI_ERR("Error pci_request_region, ret:%d\n", ret);
    80			goto error_request_region;
    81		}
    82	
    83		pci_set_master(pci_dev);
    84	
    85		start = pci_resource_start(pci_dev, mhi_dev->resn);
    86		len = pci_resource_len(pci_dev, mhi_dev->resn);
    87		mhi_cntrl->regs = ioremap_nocache(start, len);
    88		if (!mhi_cntrl->regs) {
    89			MHI_ERR("Error ioremap region\n");
    90			goto error_ioremap;
    91		}
    92	
  > 93		ret = pci_alloc_irq_vectors(pci_dev, mhi_cntrl->msi_required,
  > 94					    mhi_cntrl->msi_required, PCI_IRQ_MSI);
    95		if (IS_ERR_VALUE((ulong)ret) || ret < mhi_cntrl->msi_required) {
    96			MHI_ERR("Failed to enable MSI, ret:%d\n", ret);
    97			goto error_req_msi;
    98		}
    99	
   100		mhi_cntrl->msi_allocated = ret;
   101		mhi_cntrl->irq = kmalloc_array(mhi_cntrl->msi_allocated,
   102					       sizeof(*mhi_cntrl->irq), GFP_KERNEL);
   103		if (!mhi_cntrl->irq) {
   104			ret = -ENOMEM;
   105			goto error_alloc_msi_vec;
   106		}
   107	
   108		for (i = 0; i < mhi_cntrl->msi_allocated; i++) {
 > 109			mhi_cntrl->irq[i] = pci_irq_vector(pci_dev, i);

110 if (mhi_cntrl->irq[i] < 0) {
111 ret = mhi_cntrl->irq[i];
112 goto error_get_irq_vec;
113 }
114 }
115
116 dev_set_drvdata(&pci_dev->dev, mhi_cntrl);
117
118 /* configure runtime pm */
119 pm_runtime_set_autosuspend_delay(&pci_dev->dev, MHI_RPM_SUSPEND_TMR_MS);
120 pm_runtime_use_autosuspend(&pci_dev->dev);
121 pm_suspend_ignore_children(&pci_dev->dev, true);
122
123 /*
124 * pci framework will increment usage count (twice) before
125 * calling local device driver probe function.
126 * 1st pci.c pci_pm_init() calls pm_runtime_forbid
127 * 2nd pci-driver.c local_pci_probe calls pm_runtime_get_sync
128 * Framework expect pci device driver to call
129 * pm_runtime_put_noidle to decrement usage count after
130 * successful probe and and call pm_runtime_allow to enable
131 * runtime suspend.
132 */
133 pm_runtime_mark_last_busy(&pci_dev->dev);
134 pm_runtime_put_noidle(&pci_dev->dev);
135
136 return 0;
137
138 error_get_irq_vec:
139 kfree(mhi_cntrl->irq);
140 mhi_cntrl->irq = NULL;
141
142 error_alloc_msi_vec:
143 pci_free_irq_vectors(pci_dev);
144
145 error_req_msi:
146 iounmap(mhi_cntrl->regs);
147
148 error_ioremap:
149 pci_clear_master(pci_dev);
150
151 error_request_region:
152 pci_disable_device(pci_dev);
153
154 error_enable_device:
155 pci_release_region(pci_dev, mhi_dev->resn);
156
157 return ret;
158 }
159

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#18 lore raw

PATCH 3/4 mhi_bus: dev: netdev: add network interface driver

In reply to Sujeev Dias

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.

---
 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
Documentation/devicetree/bindings/bus/mhi.txt +36 -0
index ea1b620..172ae7b 100644
@@ -139,3 +139,39 @@ mhi_controller {
 		<driver specific properties>
 	};
 };
+
+================
+Children Devices
+================
+
+MHI netdev properties
+
+- mhi,chan
+  Usage: required
+  Value type: <string>
+  Definition: Channel name MHI netdev support
+
+- mhi,mru
+  Usage: required
+  Value type: <u32>
+  Definition: Largest packet size interface can receive in bytes.
+
+- mhi,interface-name
+  Usage: optional
+  Value type: <string>
+  Definition: Interface name to be given so clients can identify it
+
+- mhi,recycle-buf
+  Usage: optional
+  Value type: <bool>
+  Definition: Set true if interface support recycling buffers.
+
+========
+Example:
+========
+
+mhi_rmnet@0 {
+	mhi,chan = "IP_HW0";
+	mhi,interface-name = "rmnet_mhi";
+	mhi,mru = <0x4000>;
+};
drivers/bus/Kconfig +1 -0
index fb28002..cc03762 100644
@@ -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
drivers/bus/mhi/Makefile +1 -1
index c6a2a91..2382e04 100644
@@ -5,4 +5,4 @@
 # core layer
 obj-y += core/
 obj-y += controllers/
-#obj-y += devices/
+obj-y += devices/
drivers/bus/mhi/devices/Kconfig new file +10 -0
new file mode 100644
index 0000000..40f964d
@@ -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
drivers/bus/mhi/devices/Makefile new file +1 -0
new file mode 100644
index 0000000..ee12a64
@@ -0,0 +1 @@
+obj-$(CONFIG_MHI_NETDEV) +=mhi_netdev.o
drivers/bus/mhi/devices/mhi_netdev.c new file +893 -0

893 lines not on this page · raw message

Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#19 lore raw

Re: [PATCH v1 3/4] mhi_bus: dev: netdev: add network interface driver

Quoted 4 lines · Sujeev Dias

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.

Quoted 8 lines
---
 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.

Quoted 40 lines
 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
Documentation/devicetree/bindings/bus/mhi.txt +25 -0
index ea1b620..172ae7b 100644
@@ -139,3 +139,39 @@ mhi_controller {
                <driver specific properties>
        };
 };
+
+================
+Children Devices
+================
+
+MHI netdev properties
+
+- mhi,chan
+  Usage: required
+  Value type: <string>
+  Definition: Channel name MHI netdev support
 
+- mhi,mru
+  Usage: required
+  Value type: <u32>
+  Definition: Largest packet size interface can receive in bytes.
+
+- mhi,interface-name
+  Usage: optional
+  Value type: <string>
+  Definition: Interface name to be given so clients can identify it
+
+- mhi,recycle-buf
+  Usage: optional
+  Value type: <bool>
+  Definition: Set true if interface support recycling buffers.
 

Documentation/devicetree/bindings/bus/mhi.txt mhi_controller { · line 177

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +9 -0
 
+========
+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?

Quoted 15 lines
Documentation/devicetree/bindings/bus/mhi.txt +15 -0
+#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)
+

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +10 -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.

Quoted 5 lines
Documentation/devicetree/bindings/bus/mhi.txt +5 -0
+struct mhi_stats {
+       u32 rx_int;
+       u32 tx_full;
+       u32 tx_pkts;
+       u32 rx_budget_overflow;

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +10 -0
+       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

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 5 lines
Documentation/devicetree/bindings/bus/mhi.txt +5 -0
+       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.

Quoted 17 lines
Documentation/devicetree/bindings/bus/mhi.txt +17 -0
+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;
+
+       u32 mru;
+       const char *interface_name;
+       struct napi_struct napi;
+       struct net_device *ndev;
+       struct sk_buff *frag_skb;

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +10 -0
+       bool recycle_buf;
+
+       struct mhi_stats stats;
+       struct dentry *dentry;
+       enum MHI_DEBUG_LEVEL msg_lvl;
+};
+
+struct mhi_netdev_priv {
+       struct mhi_netdev *mhi_netdev;
+};

Please kill this intermediate structure and use the mhi_netdev directly.

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 2 lines
Documentation/devicetree/bindings/bus/mhi.txt +2 -0
+static struct mhi_driver mhi_netdev_driver;
+static void mhi_netdev_create_debugfs(struct mhi_netdev *mhi_netdev);

Better remove forward declarations and sort the symbols in their natural order.

Quoted 11 lines
Documentation/devicetree/bindings/bus/mhi.txt +11 -0
+static int mhi_netdev_alloc_skb(struct mhi_netdev *mhi_netdev, gfp_t gfp_t)
+{
+       u32 cur_mru = mhi_netdev->mru;
+       struct mhi_device *mhi_dev = mhi_netdev->mhi_dev;
+       struct mhi_skb_priv *skb_priv;
+       int ret;
+       struct sk_buff *skb;
+       int no_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE);
+       int i;
+
+       for (i = 0; i < no_tre; i++) {

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +10 -0
+               skb = alloc_skb(cur_mru, gfp_t);
+               if (!skb)
+                       return -ENOMEM;
+
+               read_lock_bh(&mhi_netdev->pm_lock);
+               if (unlikely(!mhi_netdev->enabled)) {
+                       MSG_ERR("Interface not enabled\n");
+                       ret = -EIO;
+                       goto error_queue;
+               }

You shouldn't normally get here when the device is disabled, I think you can remove the pm_lock and enabled members and instead make sure the netdev itself is stopped at that point.

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 4 lines
Documentation/devicetree/bindings/bus/mhi.txt +4 -0
+               spin_lock_bh(&mhi_netdev->rx_lock);
+               ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, skb,
+                                        skb_priv->size, MHI_EOT);
+               spin_unlock_bh(&mhi_netdev->rx_lock);

What does this spinlock protect?

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 8 lines
Documentation/devicetree/bindings/bus/mhi.txt +8 -0
+static void mhi_netdev_alloc_work(struct work_struct *work)
+{
+       struct mhi_netdev *mhi_netdev = container_of(work, struct mhi_netdev,
+                                                  alloc_work);
+       /* sleep about 1 sec and retry, that should be enough time
+        * for system to reclaim freed memory back.
+        */
+       const int sleep_ms =  1000;

That is a long time to wait for in the middle of a work function!

Have you tested that it's actually sufficient to make the driver survive an out-of-memory situation?

If you do need it at all, maybe use a delayed work queue that reschedules itself rather than retrying in the work queue.

Quoted 9 lines
Documentation/devicetree/bindings/bus/mhi.txt +9 -0
+static int mhi_netdev_poll(struct napi_struct *napi, int budget)
+{
+       struct net_device *dev = napi->dev;
+       struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev);
+       struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev;
+       struct mhi_device *mhi_dev = mhi_netdev->mhi_dev;
+       int rx_work = 0;
+       int ret;
+

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +10 -0
+       MSG_VERB("Entered\n");
+
+       read_lock_bh(&mhi_netdev->pm_lock);
+
+       if (!mhi_netdev->enabled) {
+               MSG_LOG("interface is disabled!\n");
+               napi_complete(napi);
+               read_unlock_bh(&mhi_netdev->pm_lock);
+               return 0;
+       }

Again, this shouldn't be required.

Quoted 24 lines
Documentation/devicetree/bindings/bus/mhi.txt +24 -0
+static int mhi_netdev_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev);
+       struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev;
+       struct mhi_device *mhi_dev = mhi_netdev->mhi_dev;
+       int res = 0;
+       struct mhi_skb_priv *tx_priv;
+
+       MSG_VERB("Entered\n");
+
+       tx_priv = (struct mhi_skb_priv *)(skb->cb);
+       tx_priv->mhi_netdev = mhi_netdev;
+       read_lock_bh(&mhi_netdev->pm_lock);
+
+       if (unlikely(!mhi_netdev->enabled)) {
+               /* Only reason interface could be disabled and we get data
+                * is due to an SSR. We do not want to stop the queue and
+                * return error. Instead we will flush all the uplink packets
+                * and return successful
+                */
+               res = NETDEV_TX_OK;
+               dev_kfree_skb_any(skb);
+               goto mhi_xmit_exit;
+       }

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +10 -0
+
+       res = mhi_queue_transfer(mhi_dev, DMA_TO_DEVICE, skb, skb->len,
+                                MHI_EOT);
+       if (res) {
+               MSG_VERB("Failed to queue with reason:%d\n", res);
+               netif_stop_queue(dev);
+               mhi_netdev->stats.tx_full++;
+               res = NETDEV_TX_BUSY;
+               goto mhi_xmit_exit;
+       }

You don't seem to have any limit on the number of queued transfers here. Since this is for a modem, it seems absolutely essential that you keep track of how many packets have been queued but not sent over the air yet.

Please add the necessary calls to netdev_sent_queue() here and netdev_completed_queue() in the mhi_netdev_xfer_ul_cb callback respectively to prevent uncontrolled buffer bloat.

Can you clarify whether mhi_netdev_xfer_ul_cb() is called after the data has been read by the modem and queued again in another buffer, or if it only gets called after we know that the packet has been sent over the air?

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 13 lines
Documentation/devicetree/bindings/bus/mhi.txt +13 -0
+static int mhi_netdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+       int rc = 0;
+
+       switch (cmd) {
+       default:
+               /* don't fail any IOCTL right now */
+               rc = 0;
+               break;
+       }
+
+       return rc;
+}

That looks wrong. You should return an error for any unknown ioctl, which is the default behavior you get without an ioctl function.

Quoted 30 lines
Documentation/devicetree/bindings/bus/mhi.txt +30 -0
+static void mhi_netdev_create_debugfs(struct mhi_netdev *mhi_netdev)
+{
+       char node_name[32];
+       int i;
+       const umode_t mode = 0600;
+       struct dentry *file;
+       struct mhi_device *mhi_dev = mhi_netdev->mhi_dev;
+
+       const struct {
+               char *name;
+               u32 *ptr;
+       } debugfs_table[] = {
+               {
+                       "rx_int",
+                       &mhi_netdev->stats.rx_int
+               },
+               {
+                       "tx_full",
+                       &mhi_netdev->stats.tx_full
+               },
+               {
+                       "tx_pkts",
+                       &mhi_netdev->stats.tx_pkts
+               },
+               {
+                       "rx_budget_overflow",
+                       &mhi_netdev->stats.rx_budget_overflow
+               },
+               {
+                       "rx_fragmentation",

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +10 -0
+                       &mhi_netdev->stats.rx_frag
+               },
+               {
+                       "alloc_failed",
+                       &mhi_netdev->stats.alloc_failed
+               },
+               {
+                       NULL, NULL
+               },
+       };

Please use the regular network statistics interfaces for this, don't roll your own.

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 7 lines
Documentation/devicetree/bindings/bus/mhi.txt +7 -0
+       /* Both tx & rx client handle contain same device info */
+       snprintf(node_name, sizeof(node_name), "%s_%04x_%02u.%02u.%02u_%u",
+                mhi_netdev->interface_name, mhi_dev->dev_id, mhi_dev->domain,
+                mhi_dev->bus, mhi_dev->slot, mhi_netdev->alias);
+
+       if (IS_ERR_OR_NULL(dentry))
+               return;

IS_ERR_OR_NULL() is basically always a bug. debugfs returns NULL only on success when it is completely disabled, which you were trying to handle separately.

Quoted 9 lines
Documentation/devicetree/bindings/bus/mhi.txt +9 -0
+static int mhi_netdev_probe(struct mhi_device *mhi_dev,
+                           const struct mhi_device_id *id)
+{
+       int ret;
+       struct mhi_netdev *mhi_netdev;
+       struct device_node *of_node = mhi_dev->dev.of_node;
+       char node_name[32];
+
+       if (!of_node)

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +10 -0
+               return -ENODEV;
+
+       mhi_netdev = devm_kzalloc(&mhi_dev->dev, sizeof(*mhi_netdev),
+                                 GFP_KERNEL);
+       if (!mhi_netdev)
+               return -ENOMEM;
+
+       mhi_netdev->alias = of_alias_get_id(of_node, "mhi_netdev");
+       if (mhi_netdev->alias < 0)
+               return -ENODEV;

Where is that alias documented?

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 4 lines
Documentation/devicetree/bindings/bus/mhi.txt +4 -0
+       ret = of_property_read_string(of_node, "mhi,interface-name",
+                                     &mhi_netdev->interface_name);
+       if (ret)
+               mhi_netdev->interface_name = mhi_netdev_driver.driver.name;

Don't couple the Linux interface name to what the hardware is called.

Arnd

#20 lore raw

Re: [PATCH v1 3/4] mhi_bus: dev: netdev: add network interface driver

Quoted 13 lines · Arnd Bergmann
Quoted 4 lines · Sujeev Dias

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.

Quoted 8 lines
---
  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 ++++++++++++++++++++++++++
Quoted 2 lines

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.

Quoted 51 lines
Quoted 39 lines
  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

Documentation/devicetree/bindings/bus/mhi.txt +25 -0
index ea1b620..172ae7b 100644
@@ -139,3 +139,39 @@ mhi_controller {
                 <driver specific properties>
         };
  };
+
+================
+Children Devices
+================
+
+MHI netdev properties
+
+- mhi,chan
+  Usage: required
+  Value type: <string>
+  Definition: Channel name MHI netdev support
 
+- mhi,mru
+  Usage: required
+  Value type: <u32>
+  Definition: Largest packet size interface can receive in bytes.
+
+- mhi,interface-name
+  Usage: optional
+  Value type: <string>
+  Definition: Interface name to be given so clients can identify it
+
+- mhi,recycle-buf
+  Usage: optional
+  Value type: <bool>
+  Definition: Set true if interface support recycling buffers.

Documentation/devicetree/bindings/bus/mhi.txt mhi_controller { · line 177

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +9 -0
 
+========
+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?

Quoted 2 lines

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",
                       &dt_name);
     if (ret)
         continue;
     if (!strcmp(mhi_dev->chan_name, dt_name))
          mhi_dev->dev.of_node = node;
Quoted 19 lines
Quoted 19 lines
Documentation/devicetree/bindings/bus/mhi.txt +19 -0
+#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)
Quoted 8 lines

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 6 lines
Documentation/devicetree/bindings/bus/mhi.txt +6 -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.

Quoted 17 lines
Quoted 5 lines
Documentation/devicetree/bindings/bus/mhi.txt +5 -0
+struct mhi_stats {
+       u32 rx_int;
+       u32 tx_full;
+       u32 tx_pkts;
+       u32 rx_budget_overflow;

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +10 -0
+       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?

Quoted 8 lines

You initialize them as

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 5 lines
Documentation/devicetree/bindings/bus/mhi.txt +5 -0
+       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.

Quoted 52 lines
Quoted 17 lines
Documentation/devicetree/bindings/bus/mhi.txt +17 -0
+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;
+
+       u32 mru;
+       const char *interface_name;
+       struct napi_struct napi;
+       struct net_device *ndev;
+       struct sk_buff *frag_skb;

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +10 -0
+       bool recycle_buf;
+
+       struct mhi_stats stats;
+       struct dentry *dentry;
+       enum MHI_DEBUG_LEVEL msg_lvl;
+};
+
+struct mhi_netdev_priv {
+       struct mhi_netdev *mhi_netdev;
+};

Please kill this intermediate structure and use the mhi_netdev directly.

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 2 lines
Documentation/devicetree/bindings/bus/mhi.txt +2 -0
+static struct mhi_driver mhi_netdev_driver;
+static void mhi_netdev_create_debugfs(struct mhi_netdev *mhi_netdev);

Better remove forward declarations and sort the symbols in their natural order.

Quoted 17 lines
Documentation/devicetree/bindings/bus/mhi.txt +17 -0
+static int mhi_netdev_alloc_skb(struct mhi_netdev *mhi_netdev, gfp_t gfp_t)
+{
+       u32 cur_mru = mhi_netdev->mru;
+       struct mhi_device *mhi_dev = mhi_netdev->mhi_dev;
+       struct mhi_skb_priv *skb_priv;
+       int ret;
+       struct sk_buff *skb;
+       int no_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE);
+       int i;
+
+       for (i = 0; i < no_tre; i++) {
+               skb = alloc_skb(cur_mru, gfp_t);
+               if (!skb)
+                       return -ENOMEM;
+
+               read_lock_bh(&mhi_netdev->pm_lock);
+               if (unlikely(!mhi_netdev->enabled)) {
Quoted 8 lines

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 4 lines
Documentation/devicetree/bindings/bus/mhi.txt +4 -0
+                       MSG_ERR("Interface not enabled\n");
+                       ret = -EIO;
+                       goto error_queue;
+               }

You shouldn't normally get here when the device is disabled, I think you can remove the pm_lock and enabled members and instead make sure the netdev itself is stopped at that point.

I will need to think about this a bit more, will address in next patch set.

Quoted 5 lines

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 4 lines
Documentation/devicetree/bindings/bus/mhi.txt +4 -0
+               spin_lock_bh(&mhi_netdev->rx_lock);
+               ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, skb,
+                                        skb_priv->size, MHI_EOT);
+               spin_unlock_bh(&mhi_netdev->rx_lock);

What does this spinlock protect?

This should answer by your next question, reason is I have this lock is because mhi_netdev_allocwork could be running in parallel while mhi_netdev_poll also calling mhi_netdev_alloc_skb(). I couldn't think of a simpler way to protect each other than using this lock. I will put a comment

Quoted 10 lines

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 8 lines
Documentation/devicetree/bindings/bus/mhi.txt +8 -0
+static void mhi_netdev_alloc_work(struct work_struct *work)
+{
+       struct mhi_netdev *mhi_netdev = container_of(work, struct mhi_netdev,
+                                                  alloc_work);
+       /* sleep about 1 sec and retry, that should be enough time
+        * for system to reclaim freed memory back.
+        */
+       const int sleep_ms =  1000;

That is a long time to wait for in the middle of a work function!

Quoted 5 lines

Have you tested that it's actually sufficient to make the driver survive an out-of-memory situation?

If you do need it at all, maybe use a delayed work queue that reschedules itself rather than retrying in the work queue.

When system running for days, we have seeing out of memory issues and re-trying does helps. I like your suggestion, will use a delayed work queue.

Quoted 12 lines
Quoted 12 lines
Documentation/devicetree/bindings/bus/mhi.txt +12 -0
+static int mhi_netdev_poll(struct napi_struct *napi, int budget)
+{
+       struct net_device *dev = napi->dev;
+       struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev);
+       struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev;
+       struct mhi_device *mhi_dev = mhi_netdev->mhi_dev;
+       int rx_work = 0;
+       int ret;
+
+       MSG_VERB("Entered\n");
+
+       read_lock_bh(&mhi_netdev->pm_lock);
Quoted 9 lines

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 7 lines
Documentation/devicetree/bindings/bus/mhi.txt +7 -0
+
+       if (!mhi_netdev->enabled) {
+               MSG_LOG("interface is disabled!\n");
+               napi_complete(napi);
+               read_unlock_bh(&mhi_netdev->pm_lock);
+               return 0;
+       }

Again, this shouldn't be required.

Without the lock how can I synchronize mhi_netdev_poll with remove()? Remove can happens anytime asynchronously whenever modem powers off. I may not needed the check, but I may need to keep the lock.

Quoted 39 lines
Quoted 24 lines
Documentation/devicetree/bindings/bus/mhi.txt +24 -0
+static int mhi_netdev_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev);
+       struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev;
+       struct mhi_device *mhi_dev = mhi_netdev->mhi_dev;
+       int res = 0;
+       struct mhi_skb_priv *tx_priv;
+
+       MSG_VERB("Entered\n");
+
+       tx_priv = (struct mhi_skb_priv *)(skb->cb);
+       tx_priv->mhi_netdev = mhi_netdev;
+       read_lock_bh(&mhi_netdev->pm_lock);
+
+       if (unlikely(!mhi_netdev->enabled)) {
+               /* Only reason interface could be disabled and we get data
+                * is due to an SSR. We do not want to stop the queue and
+                * return error. Instead we will flush all the uplink packets
+                * and return successful
+                */
+               res = NETDEV_TX_OK;
+               dev_kfree_skb_any(skb);
+               goto mhi_xmit_exit;
+       }

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +10 -0
+
+       res = mhi_queue_transfer(mhi_dev, DMA_TO_DEVICE, skb, skb->len,
+                                MHI_EOT);
+       if (res) {
+               MSG_VERB("Failed to queue with reason:%d\n", res);
+               netif_stop_queue(dev);
+               mhi_netdev->stats.tx_full++;
+               res = NETDEV_TX_BUSY;
+               goto mhi_xmit_exit;
+       }

You don't seem to have any limit on the number of queued transfers here. Since this is for a modem, it seems absolutely essential that you keep track of how many packets have been queued but not sent over the air yet.

Quoted 8 lines

Please add the necessary calls to netdev_sent_queue() here and netdev_completed_queue() in the mhi_netdev_xfer_ul_cb callback respectively to prevent uncontrolled buffer bloat.

Can you clarify whether mhi_netdev_xfer_ul_cb() is called after the data has been read by the modem and queued again in another buffer, or if it only gets called after we know that the packet has been sent over the air?

Callback comes immediately after modem read the buffer from host DDR to local DDR. Data goes thru multiple layers in modem before actually goes out over the air.

Quoted 7 lines
Quoted 7 lines
Documentation/devicetree/bindings/bus/mhi.txt +7 -0
+static int mhi_netdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+       int rc = 0;
+
+       switch (cmd) {
+       default:
+               /* don't fail any IOCTL right now */
Quoted 8 lines

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 6 lines
Documentation/devicetree/bindings/bus/mhi.txt +6 -0
+               rc = 0;
+               break;
+       }
+
+       return rc;
+}

That looks wrong. You should return an error for any unknown ioctl, which is the default behavior you get without an ioctl function.

I will remove the ioctl, will add a separate patch for supported IOCTLs.

Quoted 65 lines
Quoted 30 lines
Documentation/devicetree/bindings/bus/mhi.txt +30 -0
+static void mhi_netdev_create_debugfs(struct mhi_netdev *mhi_netdev)
+{
+       char node_name[32];
+       int i;
+       const umode_t mode = 0600;
+       struct dentry *file;
+       struct mhi_device *mhi_dev = mhi_netdev->mhi_dev;
+
+       const struct {
+               char *name;
+               u32 *ptr;
+       } debugfs_table[] = {
+               {
+                       "rx_int",
+                       &mhi_netdev->stats.rx_int
+               },
+               {
+                       "tx_full",
+                       &mhi_netdev->stats.tx_full
+               },
+               {
+                       "tx_pkts",
+                       &mhi_netdev->stats.tx_pkts
+               },
+               {
+                       "rx_budget_overflow",
+                       &mhi_netdev->stats.rx_budget_overflow
+               },
+               {
+                       "rx_fragmentation",

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt +10 -0
+                       &mhi_netdev->stats.rx_frag
+               },
+               {
+                       "alloc_failed",
+                       &mhi_netdev->stats.alloc_failed
+               },
+               {
+                       NULL, NULL
+               },
+       };

Please use the regular network statistics interfaces for this, don't roll your own.

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 7 lines
Documentation/devicetree/bindings/bus/mhi.txt +7 -0
+       /* Both tx & rx client handle contain same device info */
+       snprintf(node_name, sizeof(node_name), "%s_%04x_%02u.%02u.%02u_%u",
+                mhi_netdev->interface_name, mhi_dev->dev_id, mhi_dev->domain,
+                mhi_dev->bus, mhi_dev->slot, mhi_netdev->alias);
+
+       if (IS_ERR_OR_NULL(dentry))
+               return;

IS_ERR_OR_NULL() is basically always a bug. debugfs returns NULL only on success when it is completely disabled, which you were trying to handle separately.

Quoted 12 lines
Documentation/devicetree/bindings/bus/mhi.txt +12 -0
+static int mhi_netdev_probe(struct mhi_device *mhi_dev,
+                           const struct mhi_device_id *id)
+{
+       int ret;
+       struct mhi_netdev *mhi_netdev;
+       struct device_node *of_node = mhi_dev->dev.of_node;
+       char node_name[32];
+
+       if (!of_node)
+               return -ENODEV;
+
+       mhi_netdev = devm_kzalloc(&mhi_dev->dev, sizeof(*mhi_netdev),
Quoted 8 lines

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 7 lines
Documentation/devicetree/bindings/bus/mhi.txt +7 -0
+                                 GFP_KERNEL);
+       if (!mhi_netdev)
+               return -ENOMEM;
+
+       mhi_netdev->alias = of_alias_get_id(of_node, "mhi_netdev");
+       if (mhi_netdev->alias < 0)
+               return -ENODEV;

Where is that alias documented?

Will add to documentation.

Quoted 8 lines

Documentation/devicetree/bindings/bus/mhi.txt

Quoted 4 lines
Documentation/devicetree/bindings/bus/mhi.txt +4 -0
+       ret = of_property_read_string(of_node, "mhi,interface-name",
+                                     &mhi_netdev->interface_name);
+       if (ret)
+               mhi_netdev->interface_name = mhi_netdev_driver.driver.name;

Don't couple the Linux interface name to what the hardware is called.

Arnd

Thanks for all comments Arnd

Sujeev

Quoted 4 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#21 lore raw

PATCH 4/4 mhi_bus: dev: uci: add user space interface driver

In reply to Sujeev Dias

This module allows user space clients to transfer data between external modem and host using standard file operations.

---
 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
drivers/bus/mhi/devices/Kconfig +9 -0
index 40f964d..83b9673 100644
@@ -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
drivers/bus/mhi/devices/Makefile +1 -0
index ee12a64..300eed1 100644
@@ -1 +1,2 @@
 obj-$(CONFIG_MHI_NETDEV) +=mhi_netdev.o
+obj-$(CONFIG_MHI_UCI) +=mhi_uci.o
drivers/bus/mhi/devices/mhi_uci.c new file +662 -0

662 lines not on this page · raw message

Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#22 lore raw

Re: [PATCH v1 4/4] mhi_bus: dev: uci: add user space interface driver

Quoted 19 lines · Sujeev Dias

This module allows user space clients to transfer data between external modem and host using standard file operations.

---
 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
drivers/bus/mhi/devices/Kconfig +0 -0
index 40f964d..83b9673 100644
@@ -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

drivers/bus/mhi/devices/Kconfig config MHI_NETDEV · line 18

Quoted 10 lines
drivers/bus/mhi/devices/Kconfig +9 -0
          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.
+

Can you expand this description both in Kconfig and the patch changelog? It's not clear at all what this is good for and what the actual data is that you send over it.

What tools do you use to talk to them, can you point to a source repository here? I think that would be useful in order to decide whether we actually need a low-level interface at all, or if it should all be accessed using high-level interfaces like the network driver.

Arnd

#23 lore raw

Re: [PATCH v1 4/4] mhi_bus: dev: uci: add user space interface driver

In reply to Sujeev Dias
Thank you for the patch! Perhaps something to improve:

Hi Sujeev,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v4.17-rc2 next-20180426]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Sujeev-Dias/mhi_bus-core-Add-support-for-MHI-host-interface/20180428-065959
config: i386-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0 reproduce:

        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

In file included from drivers/bus/mhi/devices/mhi_uci.c:26:0:
include/linux/mhi.h:658:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
static inlint int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl)
^~~
In file included from include/linux/printk.h:7:0,
from include/linux/kernel.h:14,
from include/linux/list.h:9,
from include/linux/kobject.h:19,
from include/linux/cdev.h:5,
from drivers/bus/mhi/devices/mhi_uci.c:13:
drivers/bus/mhi/devices/mhi_uci.c: In function 'mhi_queue_inbound':

>> include/linux/kern_levels.h:5:18: warning: format '%ld' expects argument of type 'long int', but argument 5 has type 'size_t {aka unsigned int}' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/kern_levels.h:11:18: note: in expansion of macro 'KERN_SOH'
    #define KERN_ERR KERN_SOH "3" /* error conditions */
                     ^~~~~~~~
   include/linux/printk.h:304:9: note: in expansion of macro 'KERN_ERR'
     printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
            ^~~~~~~~
>> drivers/bus/mhi/devices/mhi_uci.c:73:4: note: in expansion of macro 'pr_err'
       pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \
       ^~~~~~
>> drivers/bus/mhi/devices/mhi_uci.c:114:3: note: in expansion of macro 'MSG_VERB'
      MSG_VERB("Allocated buf %d of %d size %ld\n", i, nr_trbs, mtu);
      ^~~~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:114:43: note: format string is defined here
      MSG_VERB("Allocated buf %d of %d size %ld\n", i, nr_trbs, mtu);
                                            ~~^
                                            %d
   In file included from include/linux/printk.h:7:0,
                    from include/linux/kernel.h:14,
                    from include/linux/list.h:9,
                    from include/linux/kobject.h:19,
                    from include/linux/cdev.h:5,
                    from drivers/bus/mhi/devices/mhi_uci.c:13:
   drivers/bus/mhi/devices/mhi_uci.c: In function 'mhi_uci_write':
   include/linux/kern_levels.h:5:18: warning: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'size_t {aka unsigned int}' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/kern_levels.h:11:18: note: in expansion of macro 'KERN_SOH'
    #define KERN_ERR KERN_SOH "3" /* error conditions */
                     ^~~~~~~~
   include/linux/printk.h:304:9: note: in expansion of macro 'KERN_ERR'
     printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
            ^~~~~~~~
>> drivers/bus/mhi/devices/mhi_uci.c:73:4: note: in expansion of macro 'pr_err'
       pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \
       ^~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:243:2: note: in expansion of macro 'MSG_VERB'
     MSG_VERB("Enter: to xfer:%lu bytes\n", count);
     ^~~~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:243:29: note: format string is defined here
     MSG_VERB("Enter: to xfer:%lu bytes\n", count);
                              ~~^
                              %u
   In file included from include/linux/printk.h:7:0,
                    from include/linux/kernel.h:14,
                    from include/linux/list.h:9,
                    from include/linux/kobject.h:19,
                    from include/linux/cdev.h:5,
                    from drivers/bus/mhi/devices/mhi_uci.c:13:
   include/linux/kern_levels.h:5:18: warning: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'size_t {aka unsigned int}' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/kern_levels.h:11:18: note: in expansion of macro 'KERN_SOH'
    #define KERN_ERR KERN_SOH "3" /* error conditions */
                     ^~~~~~~~
   include/linux/printk.h:304:9: note: in expansion of macro 'KERN_ERR'
     printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
            ^~~~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:89:4: note: in expansion of macro 'pr_err'
       pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \
       ^~~~~~
>> drivers/bus/mhi/devices/mhi_uci.c:266:4: note: in expansion of macro 'MSG_ERR'
       MSG_ERR("Failed to allocate memory %lu\n", xfer_size);
       ^~~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:266:41: note: format string is defined here
       MSG_ERR("Failed to allocate memory %lu\n", xfer_size);
                                          ~~^
                                          %u
   In file included from include/linux/printk.h:7:0,
                    from include/linux/kernel.h:14,
                    from include/linux/list.h:9,
                    from include/linux/kobject.h:19,
                    from include/linux/cdev.h:5,
                    from drivers/bus/mhi/devices/mhi_uci.c:13:
   include/linux/kern_levels.h:5:18: warning: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'size_t {aka unsigned int}' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/kern_levels.h:11:18: note: in expansion of macro 'KERN_SOH'
    #define KERN_ERR KERN_SOH "3" /* error conditions */
                     ^~~~~~~~
   include/linux/printk.h:304:9: note: in expansion of macro 'KERN_ERR'
     printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
            ^~~~~~~~
>> drivers/bus/mhi/devices/mhi_uci.c:73:4: note: in expansion of macro 'pr_err'
       pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \
       ^~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:295:2: note: in expansion of macro 'MSG_VERB'
     MSG_VERB("Exit: Number of bytes xferred:%lu\n", bytes_xfered);
     ^~~~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:295:44: note: format string is defined here
     MSG_VERB("Exit: Number of bytes xferred:%lu\n", bytes_xfered);
                                             ~~^
                                             %u
   In file included from include/linux/printk.h:7:0,
                    from include/linux/kernel.h:14,
                    from include/linux/list.h:9,
                    from include/linux/kobject.h:19,
                    from include/linux/cdev.h:5,
                    from drivers/bus/mhi/devices/mhi_uci.c:13:
   drivers/bus/mhi/devices/mhi_uci.c: In function 'mhi_uci_read':
   include/linux/kern_levels.h:5:18: warning: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'size_t {aka unsigned int}' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/kern_levels.h:11:18: note: in expansion of macro 'KERN_SOH'
    #define KERN_ERR KERN_SOH "3" /* error conditions */
                     ^~~~~~~~
   include/linux/printk.h:304:9: note: in expansion of macro 'KERN_ERR'
     printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
            ^~~~~~~~
>> drivers/bus/mhi/devices/mhi_uci.c:73:4: note: in expansion of macro 'pr_err'
       pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \
       ^~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:321:2: note: in expansion of macro 'MSG_VERB'
     MSG_VERB("Client provided buf len:%lu\n", count);
     ^~~~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:321:38: note: format string is defined here
     MSG_VERB("Client provided buf len:%lu\n", count);
                                       ~~^
                                       %u
   In file included from include/linux/printk.h:7:0,
                    from include/linux/kernel.h:14,
                    from include/linux/list.h:9,
                    from include/linux/kobject.h:19,
                    from include/linux/cdev.h:5,
                    from drivers/bus/mhi/devices/mhi_uci.c:13:
   include/linux/kern_levels.h:5:18: warning: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'size_t {aka unsigned int}' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/kern_levels.h:11:18: note: in expansion of macro 'KERN_SOH'
    #define KERN_ERR KERN_SOH "3" /* error conditions */
                     ^~~~~~~~
   include/linux/printk.h:304:9: note: in expansion of macro 'KERN_ERR'
     printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
            ^~~~~~~~
>> drivers/bus/mhi/devices/mhi_uci.c:73:4: note: in expansion of macro 'pr_err'
       pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \
       ^~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:376:2: note: in expansion of macro 'MSG_VERB'
     MSG_VERB("Copied %lu of %lu bytes\n", to_copy, uci_chan->rx_size);
     ^~~~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:376:21: note: format string is defined here
     MSG_VERB("Copied %lu of %lu bytes\n", to_copy, uci_chan->rx_size);
                      ~~^
                      %u
   In file included from include/linux/printk.h:7:0,
                    from include/linux/kernel.h:14,
                    from include/linux/list.h:9,
                    from include/linux/kobject.h:19,
                    from include/linux/cdev.h:5,
                    from drivers/bus/mhi/devices/mhi_uci.c:13:
   include/linux/kern_levels.h:5:18: warning: format '%lu' expects argument of type 'long unsigned int', but argument 4 has type 'size_t {aka unsigned int}' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/kern_levels.h:11:18: note: in expansion of macro 'KERN_SOH'
    #define KERN_ERR KERN_SOH "3" /* error conditions */
                     ^~~~~~~~
   include/linux/printk.h:304:9: note: in expansion of macro 'KERN_ERR'
     printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
            ^~~~~~~~
>> drivers/bus/mhi/devices/mhi_uci.c:73:4: note: in expansion of macro 'pr_err'
       pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \
       ^~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:376:2: note: in expansion of macro 'MSG_VERB'
     MSG_VERB("Copied %lu of %lu bytes\n", to_copy, uci_chan->rx_size);
     ^~~~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:376:28: note: format string is defined here
     MSG_VERB("Copied %lu of %lu bytes\n", to_copy, uci_chan->rx_size);
                             ~~^
                             %u
   In file included from include/linux/printk.h:7:0,
                    from include/linux/kernel.h:14,
                    from include/linux/list.h:9,
                    from include/linux/kobject.h:19,
                    from include/linux/cdev.h:5,
                    from drivers/bus/mhi/devices/mhi_uci.c:13:
   include/linux/kern_levels.h:5:18: warning: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'size_t {aka unsigned int}' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/kern_levels.h:11:18: note: in expansion of macro 'KERN_SOH'
    #define KERN_ERR KERN_SOH "3" /* error conditions */
                     ^~~~~~~~
   include/linux/printk.h:304:9: note: in expansion of macro 'KERN_ERR'
     printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
            ^~~~~~~~
>> drivers/bus/mhi/devices/mhi_uci.c:73:4: note: in expansion of macro 'pr_err'
       pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \
       ^~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:400:2: note: in expansion of macro 'MSG_VERB'
     MSG_VERB("Returning %lu bytes\n", to_copy);
     ^~~~~~~~
   drivers/bus/mhi/devices/mhi_uci.c:400:24: note: format string is defined here
     MSG_VERB("Returning %lu bytes\n", to_copy);
                         ~~^
                         %u

vim +/pr_err +73 drivers/bus/mhi/devices/mhi_uci.c

    70	
    71	#define MSG_VERB(fmt, ...) do { \
    72			if (msg_lvl <= MHI_MSG_LVL_VERBOSE) \
  > 73				pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \
    74		} while (0)
    75	
    76	#else
    77	
    78	#define MSG_VERB(fmt, ...)
    79	
    80	#endif
    81	
    82	#define MSG_LOG(fmt, ...) do { \
    83			if (msg_lvl <= MHI_MSG_LVL_INFO) \
    84				pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__); \
    85		} while (0)
    86	
    87	#define MSG_ERR(fmt, ...) do { \
    88			if (msg_lvl <= MHI_MSG_LVL_ERROR) \
  > 89				pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \
    90		} while (0)
    91	
    92	#define MAX_UCI_DEVICES (64)
    93	
    94	static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES);
    95	static struct mhi_uci_drv mhi_uci_drv;
    96	
    97	static int mhi_queue_inbound(struct uci_dev *uci_dev)
    98	{
    99		struct mhi_device *mhi_dev = uci_dev->mhi_dev;
   100		int nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE);
   101		size_t mtu = uci_dev->mtu;
   102		void *buf;
   103		struct uci_buf *uci_buf;
   104		int ret = -EIO, i;
   105	
   106		for (i = 0; i < nr_trbs; i++) {
   107			buf = kmalloc(mtu + sizeof(*uci_buf), GFP_KERNEL);
   108			if (!buf)
   109				return -ENOMEM;
   110	
   111			uci_buf = buf + mtu;
   112			uci_buf->data = buf;
   113	
 > 114			MSG_VERB("Allocated buf %d of %d size %ld\n", i, nr_trbs, mtu);
   115	
   116			ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf, mtu,
   117						 MHI_EOT);
   118			if (ret) {
   119				kfree(buf);
   120				MSG_ERR("Failed to queue buffer %d\n", i);
   121				return ret;
   122			}
   123		}
   124	
   125		return ret;
   126	}
   127	
   128	static long mhi_uci_ioctl(struct file *file,
   129				  unsigned int cmd,
   130				  unsigned long arg)
   131	{
   132		struct uci_dev *uci_dev = file->private_data;
   133		struct mhi_device *mhi_dev = uci_dev->mhi_dev;
   134		long ret = -ERESTARTSYS;
   135	
   136		mutex_lock(&uci_dev->mutex);
   137		if (uci_dev->enabled)
   138			ret = mhi_ioctl(mhi_dev, cmd, arg);
   139		mutex_unlock(&uci_dev->mutex);
   140	
   141		return ret;
   142	}
   143	
   144	static int mhi_uci_release(struct inode *inode, struct file *file)
   145	{
   146		struct uci_dev *uci_dev = file->private_data;
   147	
   148		mutex_lock(&uci_dev->mutex);
   149		uci_dev->ref_count--;
   150		if (!uci_dev->ref_count) {
   151			struct uci_buf *itr, *tmp;
   152			struct uci_chan *uci_chan;
   153	
   154			MSG_LOG("Last client left, closing node\n");
   155	
   156			if (uci_dev->enabled)
   157				mhi_unprepare_from_transfer(uci_dev->mhi_dev);
   158	
   159			/* clean inbound channel */
   160			uci_chan = &uci_dev->dl_chan;
   161			list_for_each_entry_safe(itr, tmp, &uci_chan->pending, node) {
   162				list_del(&itr->node);
   163				kfree(itr->data);
   164			}
   165			if (uci_chan->cur_buf)
   166				kfree(uci_chan->cur_buf->data);
   167	
   168			uci_chan->cur_buf = NULL;
   169	
   170			if (!uci_dev->enabled) {
   171				MSG_LOG("Node is deleted, freeing dev node\n");
   172				mutex_unlock(&uci_dev->mutex);
   173				mutex_destroy(&uci_dev->mutex);
   174				clear_bit(MINOR(uci_dev->devt), uci_minors);
   175				kfree(uci_dev);
   176				return 0;
   177			}
   178		}
   179	
   180		mutex_unlock(&uci_dev->mutex);
   181	
   182		MSG_LOG("exit: ref_count:%d\n", uci_dev->ref_count);
   183	
   184		return 0;
   185	}
   186	
   187	static unsigned int mhi_uci_poll(struct file *file, poll_table *wait)
   188	{
   189		struct uci_dev *uci_dev = file->private_data;
   190		struct mhi_device *mhi_dev = uci_dev->mhi_dev;
   191		struct uci_chan *uci_chan;
   192		unsigned int mask = 0;
   193	
   194		poll_wait(file, &uci_dev->dl_chan.wq, wait);
   195		poll_wait(file, &uci_dev->ul_chan.wq, wait);
   196	
   197		uci_chan = &uci_dev->dl_chan;
   198		spin_lock_bh(&uci_chan->lock);
   199		if (!uci_dev->enabled) {
   200			mask = POLLERR;
   201		} else if (!list_empty(&uci_chan->pending) || uci_chan->cur_buf) {
   202			MSG_VERB("Client can read from node\n");
   203			mask |= POLLIN | POLLRDNORM;
   204		}
   205		spin_unlock_bh(&uci_chan->lock);
   206	
   207		uci_chan = &uci_dev->ul_chan;
   208		spin_lock_bh(&uci_chan->lock);
   209		if (!uci_dev->enabled) {
   210			mask |= POLLERR;
   211		} else if (mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE) > 0) {
   212			MSG_VERB("Client can write to node\n");
   213			mask |= POLLOUT | POLLWRNORM;
   214		}
   215		spin_unlock_bh(&uci_chan->lock);
   216	
   217		MSG_LOG("Client attempted to poll, returning mask 0x%x\n", mask);
   218	
   219		return mask;
   220	}
   221	
   222	static ssize_t mhi_uci_write(struct file *file,
   223				     const char __user *buf,
   224				     size_t count,
   225				     loff_t *offp)
   226	{
   227		struct uci_dev *uci_dev = file->private_data;
   228		struct mhi_device *mhi_dev = uci_dev->mhi_dev;
   229		struct uci_chan *uci_chan = &uci_dev->ul_chan;
   230		size_t bytes_xfered = 0;
   231		int ret;
   232	
   233		if (!buf || !count)
   234			return -EINVAL;
   235	
   236		/* confirm channel is active */
   237		spin_lock_bh(&uci_chan->lock);
   238		if (!uci_dev->enabled) {
   239			spin_unlock_bh(&uci_chan->lock);
   240			return -ERESTARTSYS;
   241		}
   242	
   243		MSG_VERB("Enter: to xfer:%lu bytes\n", count);
   244	
   245		while (count) {
   246			size_t xfer_size;
   247			void *kbuf;
   248			enum MHI_FLAGS flags;
   249	
   250			spin_unlock_bh(&uci_chan->lock);
   251	
   252			/* wait for free descriptors */
   253			ret = wait_event_interruptible(uci_chan->wq,
   254				(!uci_dev->enabled) ||
   255				mhi_get_no_free_descriptors
   256						       (mhi_dev, DMA_TO_DEVICE) > 0);
   257	
   258			if (ret == -ERESTARTSYS) {
   259				MSG_LOG("Exit signal caught for node\n");
   260				return -ERESTARTSYS;
   261			}
   262	
   263			xfer_size = min_t(size_t, count, uci_dev->mtu);
   264			kbuf = kmalloc(xfer_size, GFP_KERNEL);
   265			if (!kbuf) {
 > 266				MSG_ERR("Failed to allocate memory %lu\n", xfer_size);

267 return -ENOMEM;
268 }
269
270 ret = copy_from_user(kbuf, buf, xfer_size);
271 if (unlikely(ret)) {
272 kfree(kbuf);
273 return ret;
274 }
275
276 spin_lock_bh(&uci_chan->lock);
277 flags = (count - xfer_size) ? MHI_EOB : MHI_EOT;
278 if (uci_dev->enabled)
279 ret = mhi_queue_transfer(mhi_dev, DMA_TO_DEVICE, kbuf,
280 xfer_size, flags);
281 else
282 ret = -ERESTARTSYS;
283
284 if (ret) {
285 kfree(kbuf);
286 goto sys_interrupt;
287 }
288
289 bytes_xfered += xfer_size;
290 count -= xfer_size;
291 buf += xfer_size;
292 }
293
294 spin_unlock_bh(&uci_chan->lock);
295 MSG_VERB("Exit: Number of bytes xferred:%lu\n", bytes_xfered);
296
297 return bytes_xfered;
298
299 sys_interrupt:
300 spin_unlock_bh(&uci_chan->lock);
301
302 return ret;
303 }
304

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#24 lore raw

[PATCH] mhi_bus: dev: uci: fix semicolon.cocci warnings

In reply to Sujeev Dias
drivers/bus/mhi/devices/mhi_uci.c:556:2-3: Unneeded semicolon

From: Fengguang Wu <[email protected]>

drivers/bus/mhi/devices/mhi_uci.c:556:2-3: Unneeded semicolon

Remove unneeded semicolon.

Generated by: scripts/coccinelle/misc/semicolon.cocci

Fixes 2064c7ebc5cb ("mhi_bus: dev: uci: add user space interface driver")
CC Sujeev Dias <[email protected]>

---

 mhi_uci.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/bus/mhi/devices/mhi_uci.c +1 -1
@@ -553,7 +553,7 @@ static int mhi_uci_probe(struct mhi_devi
 		spin_lock_init(&uci_chan->lock);
 		init_waitqueue_head(&uci_chan->wq);
 		INIT_LIST_HEAD(&uci_chan->pending);
-	};
+	}
 
 	uci_dev->mtu = id->driver_data;
 	mhi_device_set_devdata(mhi_dev, uci_dev);
#25 lore raw

Re: [PATCH v1 4/4] mhi_bus: dev: uci: add user space interface driver

In reply to Sujeev Dias
Thank you for the patch! Perhaps something to improve:

Hi Sujeev,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v4.17-rc2 next-20180426]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Sujeev-Dias/mhi_bus-core-Add-support-for-MHI-host-interface/20180428-065959

coccinelle warnings: (new ones prefixed by >>)

>> drivers/bus/mhi/devices/mhi_uci.c:556:2-3: Unneeded semicolon

Please review and possibly fold the followup patch.

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#26 lore raw

MHI code review

In reply to Sujeev Dias

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

#27 lore raw

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.

---
 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
Documentation/00-INDEX +2 -0
index 708dc4c..44e2c6b 100644
@@ -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/
Documentation/devicetree/bindings/bus/mhi.txt new file +258 -0

258 lines not on this page · raw message

Documentation/mhi.txt new file +235 -0

235 lines not on this page · raw message

drivers/bus/Kconfig +8 -0
index d1c0b60..080d3c2 100644
@@ -171,6 +171,14 @@ config DA8XX_MSTPRI
 	  configuration. Allows to adjust the priorities of all master
 	  peripherals.
 
+config MHI_BUS
+	tristate "Modem Host Interface"
+	help
+	  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.
+	  Enabling this module will allow host to communicate with external
+	  devices that support MHI protocol.
+
 source "drivers/bus/fsl-mc/Kconfig"
 
 endmenu
drivers/bus/Makefile +1 -0
index b8f036c..8fc0b3b 100644
@@ -31,3 +31,4 @@ obj-$(CONFIG_UNIPHIER_SYSTEM_BUS)	+= uniphier-system-bus.o
 obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o
 
 obj-$(CONFIG_DA8XX_MSTPRI)	+= da8xx-mstpri.o
+obj-$(CONFIG_MHI_BUS) += mhi/
drivers/bus/mhi/Makefile new file +6 -0
new file mode 100644
index 0000000..f8f14f7
@@ -0,0 +1,6 @@
+#
+# Makefile for the MHI stack
+#
+
+# core layer
+obj-y += core/
drivers/bus/mhi/core/Makefile new file +1 -0
new file mode 100644
index 0000000..a015809
@@ -0,0 +1 @@
+obj-$(CONFIG_MHI_BUS) +=mhi_init.o mhi_main.o
drivers/bus/mhi/core/mhi_init.c new file +538 -0

538 lines not on this page · raw message

drivers/bus/mhi/core/mhi_internal.h new file +238 -0

238 lines not on this page · raw message

drivers/bus/mhi/core/mhi_main.c new file +122 -0

122 lines not on this page · raw message

include/linux/mhi.h new file +341 -0

341 lines not on this page · raw message

include/linux/mod_devicetable.h +12 -0
index 7d361be..453ec01 100644
@@ -734,4 +734,16 @@ struct tb_service_id {
 #define TBSVC_MATCH_PROTOCOL_VERSION	0x0004
 #define TBSVC_MATCH_PROTOCOL_REVISION	0x0008
 
+#define MHI_NAME_SIZE 32
+
+/**
+ * struct mhi_device_id - MHI device identification
+ * @chan: MHI channel name
+ * @driver_data: driver data;
+ */
+struct mhi_device_id {
+	const char chan[MHI_NAME_SIZE];
+	kernel_ulong_t driver_data;
+};
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#28 lore raw

Re: [PATCH v2 1/7] mhi_bus: core: initial checkin for modem host interface bus driver

Quoted 23 lines · Sujeev Dias

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.

---
 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(+)
Quoted 8 lines
 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

You don't say what changed from v1 here :(

Please do so...

#29 lore raw

Re: [PATCH v2 1/7] mhi_bus: core: initial checkin for modem host interface bus driver

In reply to Sujeev Dias
Quoted 6 lines · Sujeev Dias

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.

Quoted 7 lines
---
 Documentation/00-INDEX                        |   2 +
 Documentation/devicetree/bindings/bus/mhi.txt | 258 ++++++++++++
 Documentation/mhi.txt                         | 235 +++++++++++

Do not put .txt files in the root of the documentation directory for no reason. They should be in .rst and hopefully in the proper location for where the documentation belongs.

And dt bindings always belong in a separate patch, you all know better than to mush it into a large one like this...

thanks,

greg k-h

#30 lore raw

Re: [PATCH v2 1/7] mhi_bus: core: initial checkin for modem host interface bus driver

In reply to Sujeev Dias

drivers/bus/mhi/core/mhi_init.c line 501

Quoted 5 lines · Sujeev Dias
drivers/bus/mhi/core/mhi_init.c new file +5 -0
+void mhi_driver_unregister(struct mhi_driver *mhi_drv)
+{
+	driver_unregister(&mhi_drv->driver);
+}
+EXPORT_SYMBOL(mhi_driver_unregister);

As you are just "wrapping" a core symbol here, please use EXPORT_SYMBOL_GPL(). Actually, you should do that for all of the exports here in this new bus, right?

drivers/bus/mhi/core/mhi_init.c line 530

Quoted 4 lines
drivers/bus/mhi/core/mhi_init.c new file +4 -0
+static int __init mhi_init(void)
+{
+	/* parent directory */
+	debugfs_create_dir(mhi_bus_type.name, NULL);

What do you do with this debugfs directory that you never save the dentry for? It looks like you forgot to remove it when this module is removed from the system :(

Quoted 17 lines

+++ b/drivers/bus/mhi/core/mhi_main.c

drivers/bus/mhi/core/mhi_main.c new file +15 -0
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/dma-direction.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>

drivers/bus/mhi/core/mhi_main.c line 25

Quoted 10 lines
drivers/bus/mhi/core/mhi_main.c new file +10 -0
+#include <linux/slab.h>
+#include <linux/mhi.h>
+#include "mhi_internal.h"
+
+void mhi_db_brstmode(struct mhi_controller *mhi_cntrl,
+		     struct db_cfg *db_cfg,
+		     void __iomem *db_addr,
+		     dma_addr_t wp)
+{
+}

<snip>

You have a lot of empty functions in this file, why?

include/linux/mhi.h line 63

Quoted 9 lines
include/linux/mhi.h new file +9 -0
+/**
+ * struct mhi_controller - Master controller structure for external modem
+ * @dev: Device associated with this controller
+ * @of_node: DT that has MHI configuration information
+ * @regs: Points to base of MHI MMIO register space
+ * @dev_id: PCIe device id of the external device
+ * @domain: PCIe domain the device connected to
+ * @bus: PCIe bus the device assigned to
+ * @slot: PCIe slot for the modem

Why not just save a pointer to the pci device? That way you don't have to duplicate all of these things.

Quoted 24 lines
include/linux/mhi.h new file +24 -0
+ * @iova_start: IOMMU starting address for data
+ * @iova_stop: IOMMU stop address for data
+ * @fw_image: Firmware image name for normal booting
+ * @edl_image: Firmware image name for emergency download mode
+ * @fbc_download: MHI host needs to do complete image transfer
+ * @rddm_size: RAM dump size that host should allocate for debugging purpose
+ * @sbl_size: SBL image size
+ * @seg_len: BHIe vector size
+ * @fbc_image: Points to firmware image buffer
+ * @rddm_image: Points to RAM dump buffer
+ * @max_chan: Maximum number of channels controller support
+ * @mhi_chan: Points to channel configuration table
+ * @lpm_chans: List of channels that require LPM notifications
+ * @total_ev_rings: Total # of event rings allocated
+ * @hw_ev_rings: Number of hardware event rings
+ * @sw_ev_rings: Number of software event rings
+ * @msi_required: Number of msi required to operate
+ * @msi_allocated: Number of msi allocated by bus master
+ * @irq: base irq # to request
+ * @mhi_event: MHI event ring configurations table
+ * @mhi_cmd: MHI command ring configurations table
+ * @mhi_ctxt: MHI device context, shared memory between host and device
+ * @timeout_ms: Timeout in ms for state transitions
+ * @pm_state: Power management state

include/linux/mhi.h line 97

Quoted 10 lines
include/linux/mhi.h new file +10 -0
+ * @ee: MHI device execution environment
+ * @dev_state: MHI STATE
+ * @status_cb: CB function to notify various power states to but master
+ * @link_status: Query link status in case of abnormal value read from device
+ * @runtime_get: Async runtime resume function
+ * @runtimet_put: Release votes
+ * @time_get: Return host time in us
+ * @lpm_disable: Request controller to disable link level low power modes
+ * @lpm_enable: Controller may enable link level low power modes again
+ * @priv_data: Points to bus master's private data

You list a lot of the structure's fields here, but not all of them, why?

Quoted 113 lines
include/linux/mhi.h new file +113 -0
+ */
+struct mhi_controller {
+	struct list_head node;
+	struct mhi_device *mhi_dev;
+
+	/* device node for iommu ops */
+	struct device *dev;
+	struct device_node *of_node;
+
+	/* mmio base */
+	void __iomem *regs;
+
+	/* device topology */
+	u32 dev_id;
+	u32 domain;
+	u32 bus;
+	u32 slot;
+
+	/* addressing window */
+	dma_addr_t iova_start;
+	dma_addr_t iova_stop;
+
+	/* fw images */
+	const char *fw_image;
+	const char *edl_image;
+
+	/* mhi host manages downloading entire fbc images */
+	bool fbc_download;
+	size_t rddm_size;
+	size_t sbl_size;
+	size_t seg_len;
+	u32 session_id;
+	u32 sequence_id;
+
+	/* physical channel config data */
+	u32 max_chan;
+	struct mhi_chan *mhi_chan;
+	struct list_head lpm_chans; /* these chan require lpm notification */
+
+	/* physical event config data */
+	u32 total_ev_rings;
+	u32 hw_ev_rings;
+	u32 sw_ev_rings;
+	u32 msi_required;
+	u32 msi_allocated;
+	int *irq; /* interrupt table */
+	struct mhi_event *mhi_event;
+
+	/* cmd rings */
+	struct mhi_cmd *mhi_cmd;
+
+	/* mhi context (shared with device) */
+	struct mhi_ctxt *mhi_ctxt;
+
+	u32 timeout_ms;
+
+	/* caller should grab pm_mutex for suspend/resume operations */
+	struct mutex pm_mutex;
+	bool pre_init;
+	rwlock_t pm_lock;
+	u32 pm_state;
+	u32 ee;
+	u32 dev_state;
+	bool wake_set;
+	atomic_t dev_wake;
+	atomic_t alloc_size;
+	struct list_head transition_list;
+	spinlock_t transition_lock;
+	spinlock_t wlock;
+
+	/* debug counters */
+	u32 M0, M2, M3;
+
+	/* worker for different state transitions */
+	struct work_struct st_worker;
+	struct work_struct fw_worker;
+	struct work_struct syserr_worker;
+	wait_queue_head_t state_event;
+
+	/* shadow functions */
+	void (*status_cb)(struct mhi_controller *mhi_cntrl, void *priv,
+			  enum MHI_CB cb);
+	int (*link_status)(struct mhi_controller *mhi_cntrl, void *priv);
+	void (*wake_get)(struct mhi_controller *mhi_cntrl, bool override);
+	void (*wake_put)(struct mhi_controller *mhi_cntrl, bool override);
+	int (*runtime_get)(struct mhi_controller *mhi_cntrl, void *priv);
+	void (*runtime_put)(struct mhi_controller *mhi_cntrl, void *priv);
+	void (*lpm_disable)(struct mhi_controller *mhi_cntrl, void *priv);
+	void (*lpm_enable)(struct mhi_controller *mhi_cntrl, void *priv);
+	int (*map_single)(struct mhi_controller *mhi_cntrl,
+			  struct mhi_buf_info *buf);
+	void (*unmap_single)(struct mhi_controller *mhi_cntrl,
+			     struct mhi_buf_info *buf);
+
+	/* channel to control DTR messaging */
+	struct mhi_device *dtr_dev;
+
+	/* bounce buffer settings */
+	bool bounce_buf;
+	size_t buffer_len;
+
+	/* controller specific data */
+	void *priv_data;
+	void *log_buf;
+	struct dentry *dentry;
+	struct dentry *parent;
+};
+
+/**
+ * struct mhi_device - mhi device structure associated bind to channel
+ * @dev: Device associated with the channels
+ * @mtu: Maximum # of bytes controller support
+ * @ul_chan_id: MHI channel id for UL transfer

include/linux/mhi.h line 220

Quoted 10 lines
include/linux/mhi.h new file +10 -0
+ * @dl_chan_id: MHI channel id for DL transfer
+ * @tiocm: Device current terminal settings
+ * @priv: Driver private data
+ */
+struct mhi_device {
+	struct device dev;
+	u32 dev_id;
+	u32 domain;
+	u32 bus;
+	u32 slot;

Same comment as above, why duplicate this and just not save the pointer to the pci device?

include/linux/mhi.h line 232

Quoted 12 lines
include/linux/mhi.h new file +12 -0
+	size_t mtu;
+	int ul_chan_id;
+	int dl_chan_id;
+	int ul_event_id;
+	int dl_event_id;
+	u32 tiocm;
+	const struct mhi_device_id *id;
+	const char *chan_name;
+	struct mhi_controller *mhi_cntrl;
+	struct mhi_chan *ul_chan;
+	struct mhi_chan *dl_chan;
+	atomic_t dev_wake;

What is dev_wake for?

include/linux/mhi.h line 234

Quoted 2 lines
include/linux/mhi.h new file +2 -0
+	enum mhi_device_type dev_type;
+	void *priv_data;

Why do you need priv_data? What's wrong with using the space in struct device instead?

include/linux/mhi.h line 239

Quoted 5 lines
include/linux/mhi.h new file +5 -0
+	int (*ul_xfer)(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
+		       void *buf, size_t len, enum MHI_FLAGS flags);
+	int (*dl_xfer)(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
+		       void *buf, size_t len, enum MHI_FLAGS flags);
+	void (*status_cb)(struct mhi_device *mhi_dev, enum MHI_CB cb);

Why does a device have function call backs in it? Shouldn't those belong to a driver?

Quoted 23 lines
include/linux/mhi.h new file +23 -0
+};
+
+/**
+ * struct mhi_result - Completed buffer information
+ * @buf_addr: Address of data buffer
+ * @dir: Channel direction
+ * @bytes_xfer: # of bytes transferred
+ * @transaction_status: Status of last trasnferred
+ */
+struct mhi_result {
+	void *buf_addr;
+	enum dma_data_direction dir;
+	size_t bytes_xferd;
+	int transaction_status;
+};
+
+/**
+ * struct mhi_driver - mhi driver information
+ * @id_table: NULL terminated channel ID names
+ * @ul_xfer_cb: UL data transfer callback
+ * @dl_xfer_cb: DL data transfer callback
+ * @status_cb: Asynchronous status callback
+ */

include/linux/mhi.h line 272

Quoted 10 lines
include/linux/mhi.h new file +10 -0
+struct mhi_driver {
+	const struct mhi_device_id *id_table;
+	int (*probe)(struct mhi_device *mhi_dev,
+		     const struct mhi_device_id *id);
+	void (*remove)(struct mhi_device *mhi_dev);
+	void (*ul_xfer_cb)(struct mhi_device *mhi_dev,
+			   struct mhi_result *result);
+	void (*dl_xfer_cb)(struct mhi_device *mhi_dev,
+			   struct mhi_result *result);
+	void (*status_cb)(struct mhi_device *mhi_dev, enum MHI_CB mhi_cb);

See, they are here in a driver!

include/linux/mhi.h line 282

Quoted 4 lines
include/linux/mhi.h new file +4 -0
+static inline void mhi_device_set_devdata(struct mhi_device *mhi_dev,
+					  void *priv)
+{
+	mhi_dev->priv_data = priv;

Again, what's wrong with the device's private data pointer?

thanks,

greg k-h

maintainer
#31 lore raw

Re: [PATCH v2 1/7] mhi_bus: core: initial checkin for modem host interface bus driver

In reply to Sujeev Dias
Quoted 6 lines · Sujeev Dias

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.

Quoted 6 lines
---
 Documentation/00-INDEX                        |   2 +
 Documentation/devicetree/bindings/bus/mhi.txt | 258 ++++++++++++

As Greg said, separate patch.

Quoted 28 lines
 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
Documentation/devicetree/bindings/bus/mhi.txt new file +2 -0
new file mode 100644
index 0000000..19deb84
@@ -0,0 +1,258 @@
+MHI Host Interface
+

Documentation/devicetree/bindings/bus/mhi.txt line 12

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+MHI used by the host to control and communicate with modem over
+high speed peripheral bus.
+
+==============
+Node Structure
+==============
+
+Main node properties:
+
+- mhi,max-channels

mhi is not a vendor. mhi-max-channels. Same for rest. Or maybe just drop 'mhi' completely.

Documentation/devicetree/bindings/bus/mhi.txt line 20

Quoted 8 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +8 -0
+  Usage: required
+  Value type: <u32>
+  Definition: Maximum number of channels supported by this controller
+
+- mhi,timeout
+  Usage: optional
+  Value type: <u32>
+  Definition: Maximum timeout in ms wait for state and cmd completion

Needs a unit suffix.

Documentation/devicetree/bindings/bus/mhi.txt line 27

Quoted 7 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +7 -0
+
+- mhi,use-bb
+  Usage: optional
+  Value type: <bool>
+  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.

How is this related to PCI?

"atomic allocation" has nothing to do with bindings.

Quoted 11 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +11 -0
+
+- mhi,buffer-len
+  Usage: optional
+  Value type: <bool>
+  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:
+============================

Documentation/devicetree/bindings/bus/mhi.txt line 48

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+
+- reg
+  Usage: required
+  Value type: <u32>
+  Definition: physical channel number
+
+- label
+  Usage: required
+  Value type: <string>
+  Definition: given name for the channel

Why does the user need this?

Quoted 75 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +75 -0
+
+- mhi,num-elements
+  Usage: optional
+  Value type: <u32>
+  Definition: Number of elements transfer ring support
+
+- mhi,event-ring
+  Usage: required
+  Value type: <u32>
+  Definition: Event ring index associated with this channel
+
+- mhi,chan-dir
+  Usage: required
+  Value type: <u32>
+  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: <u32>
+  Definition: Channel execution enviornment as defined by enum MHI_EE
+	1 = Bootloader stage
+	2 = AMSS mode
+
+- mhi,pollcfg
+  Usage: optional
+  Value type: <u32>
+  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: <u32>
+  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: <u32>
+  Definition: Channel doorbell mode configuration as defined by enum
+	MHI_BRSTMODE
+	2 = burst mode disabled
+	3 = burst mode enabled
+
+- mhi,lpm-notify
+  Usage: optional
+  Value type: <bool>
+  Definition: This channel master require low power mode enter and exit
+  notifications from mhi bus master.
+
+- mhi,offload-chan
+  Usage: optional
+  Value type: <bool>
+  Definition: Client managed channel, MHI host only involved in setting up
+	the data path, not involved in active data path.
+
+- mhi,db-mode-switch
+  Usage: optional
+  Value type: <bool>
+  Definition: Must switch to doorbell mode whenever MHI M0 state transition
+	happens.
+
+- mhi,auto-queue
+  Usage: optional
+  Value type: <bool>

Documentation/devicetree/bindings/bus/mhi.txt line 133

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+  Definition: MHI bus driver will pre-allocate buffers for this channel and
+	queue to hardware. If set, client not allowed to queue buffers. Valid
+	only for downlink direction.
+
+- mhi,auto-start
+  Usage: optional
+  Value type: <bool>
+  Definition: MHI host driver to automatically start channels once mhi device
+	driver probe is complete. This should be only set true if initial
+	handshake iniaitead by external modem.

typo

Quoted 50 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +50 -0
+
+==========================
+mhi event node properties:
+==========================
+
+- mhi,num-elements
+  Usage: required
+  Value type: <u32>
+  Definition: Number of elements event ring support
+
+- mhi,intmod
+  Usage: required
+  Value type: <u32>
+  Definition: interrupt moderation time in ms
+
+- mhi,msi
+  Usage: required
+  Value type: <u32>
+  Definition: MSI associated with this event ring
+
+- mhi,chan
+  Usage: optional
+  Value type: <u32>
+  Definition: Dedicated channel number, if it's a dedicated event ring
+
+- mhi,priority
+  Usage: required
+  Value type: <u32>
+  Definition: Event ring priority, set to 1 for now
+
+- mhi,brstmode
+  Usage: required
+  Value type: <u32>
+  Definition: Event doorbell mode configuration as defined by
+	enum MHI_BRSTMODE
+		2 = burst mode disabled
+		3 = burst mode enabled
+
+- mhi,data-type
+  Usage: optional
+  Value type: <u32>
+  Definition: Type of data this event ring will process as defined
+	by enum mhi_er_data_type
+		0 = process data packets (default)
+		1 = process mhi control packets
+
+- mhi,hw-ev
+  Usage: optional
+  Value type: <bool>
+  Definition: Event ring associated with hardware channels

Documentation/devicetree/bindings/bus/mhi.txt line 193

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+
+- mhi,client-manage
+  Usage: optional
+  Value type: <bool>
+  Definition: Client manages the event ring (use by napi_poll)
+
+- mhi,offload
+  Usage: optional
+  Value type: <bool>
+  Definition: Event ring associated with offload channel

This is a lot of properties. I suspect that many of these should be implied by the modem device or be driver settings. If the modems are PCI devices, then you should be able to determine a lot from the PCI VID/PIDs.

I'm not sure that a bus is appropriate here either. This looks like the next layer up. How's it different than a programming model for some ethernet NIC?

Rob

reviewer
#32 lore raw

Re: [PATCH v2 1/7] mhi_bus: core: initial checkin for modem host interface bus driver

In reply to Sujeev Dias
Quoted 3 lines · Sujeev Dias

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.

communicate

Quoted 36 lines

This module will allow host to communicate with external devices that support MHI protocol.

---
 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
Documentation/devicetree/bindings/bus/mhi.txt new file +0 -0
new file mode 100644
index 0000000..19deb84

Documentation/devicetree/bindings/bus/mhi.txt line 3

Quoted 3 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +3 -0
@@ -0,0 +1,258 @@
+MHI Host Interface
+
+MHI used by the host to control and communicate with modem over

MHI is used

Quoted 59 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +59 -0
+high speed peripheral bus.
+
+==============
+Node Structure
+==============
+
+Main node properties:
+
+- mhi,max-channels
+  Usage: required
+  Value type: <u32>
+  Definition: Maximum number of channels supported by this controller
+
+- mhi,timeout
+  Usage: optional
+  Value type: <u32>
+  Definition: Maximum timeout in ms wait for state and cmd completion
+
+- mhi,use-bb
+  Usage: optional
+  Value type: <bool>
+  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: <bool>
+  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: <u32>
+  Definition: physical channel number
+
+- label
+  Usage: required
+  Value type: <string>
+  Definition: given name for the channel
+
+- mhi,num-elements
+  Usage: optional
+  Value type: <u32>
+  Definition: Number of elements transfer ring support
+
+- mhi,event-ring
+  Usage: required
+  Value type: <u32>
+  Definition: Event ring index associated with this channel
+
+- mhi,chan-dir
+  Usage: required
+  Value type: <u32>

Documentation/devicetree/bindings/bus/mhi.txt line 72

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+  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: <u32>
+  Definition: Channel execution enviornment as defined by enum MHI_EE

environment

Quoted 51 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +51 -0
+	1 = Bootloader stage
+	2 = AMSS mode
+
+- mhi,pollcfg
+  Usage: optional
+  Value type: <u32>
+  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: <u32>
+  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: <u32>
+  Definition: Channel doorbell mode configuration as defined by enum
+	MHI_BRSTMODE
+	2 = burst mode disabled
+	3 = burst mode enabled
+
+- mhi,lpm-notify
+  Usage: optional
+  Value type: <bool>
+  Definition: This channel master require low power mode enter and exit
+  notifications from mhi bus master.
+
+- mhi,offload-chan
+  Usage: optional
+  Value type: <bool>
+  Definition: Client managed channel, MHI host only involved in setting up
+	the data path, not involved in active data path.
+
+- mhi,db-mode-switch
+  Usage: optional
+  Value type: <bool>
+  Definition: Must switch to doorbell mode whenever MHI M0 state transition
+	happens.
+
+- mhi,auto-queue
+  Usage: optional
+  Value type: <bool>

Documentation/devicetree/bindings/bus/mhi.txt line 133

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +10 -0
+  Definition: MHI bus driver will pre-allocate buffers for this channel and
+	queue to hardware. If set, client not allowed to queue buffers. Valid
+	only for downlink direction.
+
+- mhi,auto-start
+  Usage: optional
+  Value type: <bool>
+  Definition: MHI host driver to automatically start channels once mhi device
+	driver probe is complete. This should be only set true if initial
+	handshake iniaitead by external modem.

initiated

Quoted 131 lines
Documentation/devicetree/bindings/bus/mhi.txt new file +125 -0
+
+==========================
+mhi event node properties:
+==========================
+
+- mhi,num-elements
+  Usage: required
+  Value type: <u32>
+  Definition: Number of elements event ring support
+
+- mhi,intmod
+  Usage: required
+  Value type: <u32>
+  Definition: interrupt moderation time in ms
+
+- mhi,msi
+  Usage: required
+  Value type: <u32>
+  Definition: MSI associated with this event ring
+
+- mhi,chan
+  Usage: optional
+  Value type: <u32>
+  Definition: Dedicated channel number, if it's a dedicated event ring
+
+- mhi,priority
+  Usage: required
+  Value type: <u32>
+  Definition: Event ring priority, set to 1 for now
+
+- mhi,brstmode
+  Usage: required
+  Value type: <u32>
+  Definition: Event doorbell mode configuration as defined by
+	enum MHI_BRSTMODE
+		2 = burst mode disabled
+		3 = burst mode enabled
+
+- mhi,data-type
+  Usage: optional
+  Value type: <u32>
+  Definition: Type of data this event ring will process as defined
+	by enum mhi_er_data_type
+		0 = process data packets (default)
+		1 = process mhi control packets
+
+- mhi,hw-ev
+  Usage: optional
+  Value type: <bool>
+  Definition: Event ring associated with hardware channels
+
+- mhi,client-manage
+  Usage: optional
+  Value type: <bool>
+  Definition: Client manages the event ring (use by napi_poll)
+
+- mhi,offload
+  Usage: optional
+  Value type: <bool>
+  Definition: Event ring associated with offload channel
+
+
+Children node properties:
+
+MHI drivers that require DT can add driver specific information as a child node.
+
+- mhi,chan
+  Usage: Required
+  Value type: <string>
+  Definition: Channel name
+
+========
+Example:
+========
+mhi_controller {
+	mhi,max-channels = <105>;
+
+	mhi_chan@0 {
+		reg = <0>;
+		label = "LOOPBACK";
+		mhi,num-elements = <64>;
+		mhi,event-ring = <2>;
+		mhi,chan-dir = <1>;
+		mhi,data-type = <0>;
+		mhi,doorbell-mode = <2>;
+		mhi,ee = <2>;
+	};
+
+	mhi_chan@1 {
+		reg = <1>;
+		label = "LOOPBACK";
+		mhi,num-elements = <64>;
+		mhi,event-ring = <2>;
+		mhi,chan-dir = <2>;
+		mhi,data-type = <0>;
+		mhi,doorbell-mode = <2>;
+		mhi,ee = <2>;
+	};
+
+	mhi_event@0 {
+		mhi,num-elements = <32>;
+		mhi,intmod = <1>;
+		mhi,msi = <1>;
+		mhi,chan = <0>;
+		mhi,priority = <1>;
+		mhi,bstmode = <2>;
+		mhi,data-type = <1>;
+	};
+
+	mhi_event@1 {
+		mhi,num-elements = <256>;
+		mhi,intmod = <1>;
+		mhi,msi = <2>;
+		mhi,chan = <0>;
+		mhi,priority = <1>;
+		mhi,bstmode = <2>;
+	};
+
+	mhi,timeout = <500>;
+
+	children_node {
+		mhi,chan = "LOOPBACK"
+		<driver specific properties>
+	};
+};
Documentation/mhi.txt new file +0 -0
new file mode 100644
index 0000000..1c501f1

Documentation/mhi.txt line 6

Quoted 6 lines
Documentation/mhi.txt new file +6 -0
@@ -0,0 +1,235 @@
+Overview of Linux kernel MHI support
+====================================
+
+Modem-Host Interface (MHI)
+=========================
+MHI used by the host to control and communicate with modem over high speed

MHI is used

Documentation/mhi.txt line 7

Quoted 1 line
Documentation/mhi.txt new file +1 -0
+peripheral bus. Even though MHI can be easily adapt to any peripheral buses,

adapted

Documentation/mhi.txt line 8

Quoted 1 line
Documentation/mhi.txt new file +1 -0
+primarily used with PCIe based devices. The host has one or more PCIe root

it is primarily used with

Documentation/mhi.txt line 10

Quoted 2 lines
Documentation/mhi.txt new file +2 -0
+ports connected to modem device. The host has limited access to device memory
+space, including register configuration and control the device operation.

and control of the

Quoted 6 lines
Documentation/mhi.txt new file +6 -0
+Data transfers are invoked from the device.
+
+All data structures used by MHI are in the host system memory. Using PCIe
+interface, the device accesses those data structures. MHI data structures and
+data buffers in the host system memory regions are mapped for device.
+

Documentation/mhi.txt line 26

Quoted 10 lines
Documentation/mhi.txt new file +10 -0
+Memory spaces
+-------------
+PCIe Configurations : Used for enumeration and resource management, such as
+interrupt and base addresses.  This is done by mhi control driver.
+
+MMIO
+----
+MHI MMIO : Memory mapped IO consists of set of registers in the device hardware,
+which are mapped to the host memory space through PCIe base address register
+(BAR)

(BAR).

Quoted 48 lines
Documentation/mhi.txt new file +48 -0
+
+MHI control registers : Access to MHI configurations registers
+(struct mhi_controller.regs).
+
+MHI BHI register: Boot host interface registers (struct mhi_controller.bhi) used
+for firmware download before MHI initialization.
+
+Channel db array : Doorbell registers (struct mhi_chan.tre_ring.db_addr) used by
+host to notify device there is new work to do.
+
+Event db array : Associated with event context array
+(struct mhi_event.ring.db_addr), host uses to notify device free events are
+available.
+
+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;
+
+Event context array : All event configurations are organized in event context
+data array.
+
+struct mhi_ctxt.er_ctxt;
+struct __packed mhi_event_ctxt;
+
+Event rings: Used by device to send completion and state transition messages to
+host
+
+struct mhi_event.ring;
+struct __packed mhi_tre;
+
+Command context array: All command configurations are organized in command
+context data array.
+
+struct __packed mhi_cmd_ctxt;
+struct mhi_ctxt.cmd_ctxt;

Documentation/mhi.txt line 84

Quoted 10 lines
Documentation/mhi.txt new file +10 -0
+
+Command rings: Used by host to send MHI commands to device
+
+struct __packed mhi_tre;
+struct mhi_cmd.ring;
+
+Transfer rings
+--------------
+MHI channels are logical, unidirectional data pipes between host and device.
+Each channel associated with a single transfer ring.  The data direction can be

channel is associated

Documentation/mhi.txt line 96

Quoted 12 lines
Documentation/mhi.txt new file +12 -0
+either inbound (device to host) or outbound (host to device).  Transfer
+descriptors are managed by using transfer rings, which are defined for each
+channel between device and host and resides in the host memory.
+
+Transfer ring Pointer:	  	Transfer Ring Array
+[Read Pointer (RP)] ----------->[Ring Element] } TD
+[Write Pointer (WP)]-		[Ring Element]
+                     -		[Ring Element]
+		      --------->[Ring Element]
+				[Ring Element]
+
+1. Host allocate memory for transfer ring

allocates

Documentation/mhi.txt line 101

Quoted 5 lines
Documentation/mhi.txt new file +5 -0
+2. Host sets base, read pointer, write pointer in corresponding channel context
+3. Ring is considered empty when RP == WP
+4. Ring is considered full when WP + 1 == RP
+4. RP indicates the next element to be serviced by device
+4. When host new buffer to send, host update the Ring element with buffer

host has new buffer to send, host updates

Documentation/mhi.txt line 103

Quoted 2 lines
Documentation/mhi.txt new file +2 -0
+   information
+5. Host increment the WP to next element

increments

Quoted 5 lines
Documentation/mhi.txt new file +5 -0
+6. Ring the associated channel DB.
+
+Event rings
+-----------
+Events from the device to host are organized in event rings and defined in event

Documentation/mhi.txt line 118

Quoted 10 lines
Documentation/mhi.txt new file +10 -0
+descriptors.  Event rings are array of EDs that resides in the host memory.
+
+Transfer ring Pointer:	  	Event Ring Array
+[Read Pointer (RP)] ----------->[Ring Element] } ED
+[Write Pointer (WP)]-		[Ring Element]
+                     -		[Ring Element]
+		      --------->[Ring Element]
+				[Ring Element]
+
+1. Host allocate memory for event ring

allocates

Documentation/mhi.txt line 124

Quoted 6 lines
Documentation/mhi.txt new file +6 -0
+2. Host sets base, read pointer, write pointer in corresponding channel context
+3. Both host and device has local copy of RP, WP
+3. Ring is considered empty (no events to service) when WP + 1 == RP
+4. Ring is full of events when RP == WP
+4. RP - 1 = last event device programmed
+4. When there is a new event device need to send, device update ED pointed by RP

needs to send, device updates

Documentation/mhi.txt line 125

Quoted 1 line
Documentation/mhi.txt new file +1 -0
+5. Device increment RP to next element

increments

Documentation/mhi.txt line 126

Quoted 1 line
Documentation/mhi.txt new file +1 -0
+6. Device trigger and interrupt

triggers an interrupt

Documentation/mhi.txt line 130

Quoted 4 lines
Documentation/mhi.txt new file +4 -0
+
+Example Operation for data transfer:
+
+1. Host prepare TD with buffer information

prepares

Documentation/mhi.txt line 131

Quoted 1 line
Documentation/mhi.txt new file +1 -0
+2. Host increment Chan[id].ctxt.WP

increments

Documentation/mhi.txt line 132

Quoted 1 line
Documentation/mhi.txt new file +1 -0
+3. Host ring channel DB register

rings

Documentation/mhi.txt line 133

Quoted 1 line
Documentation/mhi.txt new file +1 -0
+4. Device wakes up process the TD

wakes up to process the TD

Documentation/mhi.txt line 134

Quoted 1 line
Documentation/mhi.txt new file +1 -0
+5. Device generate a completion event for that TD by updating ED

generates

Documentation/mhi.txt line 135

Quoted 1 line
Documentation/mhi.txt new file +1 -0
+6. Device increment Event[id].ctxt.RP

increments

Documentation/mhi.txt line 136

Quoted 1 line
Documentation/mhi.txt new file +1 -0
+7. Device trigger MSI to wake host

triggers

Documentation/mhi.txt line 137

Quoted 1 line
Documentation/mhi.txt new file +1 -0
+8. Host wakes up and check event ring for completion event

and checks

Documentation/mhi.txt line 138

Quoted 1 line
Documentation/mhi.txt new file +1 -0
+9. Host update the Event[i].ctxt.WP to indicate processed of completion event.

updates processing

Documentation/mhi.txt line 147

Quoted 9 lines
Documentation/mhi.txt new file +9 -0
+
+MHI States
+----------
+
+enum MHI_STATE {
+MHI_STATE_RESET : MHI is in reset state, POR state. Host is not allowed to
+		  access device MMIO register space.
+MHI_STATE_READY : Device is ready for initialization. Host can start MHI
+		  initialization by programming MMIO

MMIO.

Documentation/mhi.txt line 158

Quoted 11 lines
Documentation/mhi.txt new file +11 -0
+MHI_STATE_M0 : MHI is in fully active state, data transfer is active
+MHI_STATE_M1 : Device in a suspended state
+MHI_STATE_M2 : MHI in low power mode, device may enter lower power mode.
+MHI_STATE_M3 : Both host and device in suspended state.  PCIe link is not
+	       accessible to device.
+
+MHI Initialization
+------------------
+
+1. After system boots, the device is enumerated over PCIe interface
+2. Host allocate MHI context for event, channel and command arrays

allocates

Documentation/mhi.txt line 160

Quoted 2 lines
Documentation/mhi.txt new file +2 -0
+3. Initialize context array, and prepare interrupts
+3. Host waits until device enter READY state

enters

Documentation/mhi.txt line 171

Quoted 11 lines
Documentation/mhi.txt new file +11 -0
+4. Program MHI MMIO registers and set device into MHI_M0 state
+5. Wait for device to enter M0 state
+
+Linux Software Architecture
+===========================
+
+MHI Controller
+--------------
+MHI controller is also the MHI bus master. In charge of managing the physical
+link between host and device.  Not involved in actual data transfer.  At least
+for PCIe based buses, for other type of bus, we can expand to add support.

^^^^^ Too many sentence fragments...

Quoted 28 lines
Documentation/mhi.txt new file +28 -0
+
+Roles:
+1. Turn on PCIe bus and configure the link
+2. Configure MSI, SMMU, and IOMEM
+3. Allocate struct mhi_controller and register with MHI bus framework
+2. Initiate power on and shutdown sequence
+3. Initiate suspend and resume
+
+Usage
+-----
+
+1. Allocate control data structure by calling mhi_alloc_controller()
+2. Initialize mhi_controller with all the known information such as:
+   - Device Topology
+   - IOMMU window
+   - IOMEM mapping
+   - Device to use for memory allocation, and of_node with DT configuration
+   - Configure asynchronous callback functions
+3. Register MHI controller with MHI bus framework by calling
+   of_register_mhi_controller()
+
+After successfully registering controller can initiate any of these power modes:
+
+1. Power up sequence
+   - mhi_prepare_for_power_up()
+   - mhi_async_power_up()
+   - mhi_sync_power_up()
+2. Power down sequence

Documentation/mhi.txt line 209

Quoted 10 lines
Documentation/mhi.txt new file +10 -0
+   - mhi_power_down()
+   - mhi_unprepare_after_power_down()
+3. Initiate suspend
+   - mhi_pm_suspend()
+4. Initiate resume
+   - mhi_pm_resume()
+
+MHI Devices
+-----------
+Logical device that bind to maximum of two physical MHI channels. Once MHI is in

^^^^^ not-a-sentence.

Documentation/mhi.txt line 210

Quoted 1 line
Documentation/mhi.txt new file +1 -0
+powered on state, each supported channel by controller will be allocated as a

as an

Documentation/mhi.txt line 213

Quoted 3 lines
Documentation/mhi.txt new file +3 -0
+mhi_device.
+
+Each supported device would be enumerated under

how about:
Each supported device is enumerated in /sys/bus/mhi/devices

Quoted 77 lines
Documentation/mhi.txt new file +22 -0
+/sys/bus/mhi/devices/
+
+struct mhi_device;
+
+MHI Driver
+----------
+Each MHI driver can bind to one or more MHI devices. MHI host driver will bind
+mhi_device to mhi_driver.
+
+All registered drivers are visible under
+/sys/bus/mhi/drivers/
+
+struct mhi_driver;
+
+Usage
+-----
+
+1. Register driver using mhi_driver_register
+2. Before sending data, prepare device for transfer by calling
+   mhi_prepare_for_transfer
+3. Initiate data transfer by calling mhi_queue_transfer
+4. After finish, call mhi_unprepare_from_transfer to end data transfer
include/linux/mhi.h new file +47 -0
new file mode 100644
index 0000000..c80685e9
@@ -0,0 +1,341 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ */
+#ifndef _MHI_H_
+#define _MHI_H_
+
+struct mhi_chan;
+struct mhi_event;
+struct mhi_ctxt;
+struct mhi_cmd;
+struct mhi_buf_info;
+
+/**
+ * enum MHI_CB - MHI callback
+ * @MHI_CB_IDLE: MHI entered idle state
+ * @MHI_CB_PENDING_DATA: New data available for client to process
+ * @MHI_CB_LPM_ENTER: MHI host entered low power mode
+ * @MHI_CB_LPM_EXIT: MHI host about to exit low power mode
+ * @MHI_CB_EE_RDDM: MHI device entered RDDM execution enviornment
+ */
+enum MHI_CB {
+	MHI_CB_IDLE,
+	MHI_CB_PENDING_DATA,
+	MHI_CB_LPM_ENTER,
+	MHI_CB_LPM_EXIT,
+	MHI_CB_EE_RDDM,
+};
+
+/**
+ * enum MHI_FLAGS - Transfer flags
+ * @MHI_EOB: End of buffer for bulk transfer
+ * @MHI_EOT: End of transfer
+ * @MHI_CHAIN: Linked transfer
+ */
+enum MHI_FLAGS {
+	MHI_EOB,
+	MHI_EOT,
+	MHI_CHAIN,
+};
+
+/**
+ * enum mhi_device_type - Device types
+ * @MHI_XFER_TYPE: Handles data transfer
+ * @MHI_TIMESYNC_TYPE: Use for timesync feature
+ * @MHI_CONTROLLER_TYPE: Control device

include/linux/mhi.h

Quoted 10 lines
include/linux/mhi.h new file +9 -0
+ */
+enum mhi_device_type {
+	MHI_XFER_TYPE,
+	MHI_TIMESYNC_TYPE,
+	MHI_CONTROLLER_TYPE,
+};
+
 
+/**
+ * struct mhi_device - mhi device structure associated bind to channel

^^^ I don't understand what that is trying to say.

Quoted 30 lines

+ * @dev: Device associated with the channels
+ * @mtu: Maximum # of bytes controller support
+ * @ul_chan_id: MHI channel id for UL transfer
+ * @dl_chan_id: MHI channel id for DL transfer
+ * @tiocm: Device current terminal settings
+ * @priv: Driver private data
+ */

include/linux/mhi.h new file +23 -0
+struct mhi_device {
+	struct device dev;
+	u32 dev_id;
+	u32 domain;
+	u32 bus;
+	u32 slot;
+	size_t mtu;
+	int ul_chan_id;
+	int dl_chan_id;
+	int ul_event_id;
+	int dl_event_id;
+	u32 tiocm;
+	const struct mhi_device_id *id;
+	const char *chan_name;
+	struct mhi_controller *mhi_cntrl;
+	struct mhi_chan *ul_chan;
+	struct mhi_chan *dl_chan;
+	atomic_t dev_wake;
+	enum mhi_device_type dev_type;
+	void *priv_data;
+	int (*ul_xfer)(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
+		       void *buf, size_t len, enum MHI_FLAGS flags);
+	int (*dl_xfer)(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,

include/linux/mhi.h line 247

Quoted 10 lines
include/linux/mhi.h new file +10 -0
+		       void *buf, size_t len, enum MHI_FLAGS flags);
+	void (*status_cb)(struct mhi_device *mhi_dev, enum MHI_CB cb);
+};
+
+/**
+ * struct mhi_result - Completed buffer information
+ * @buf_addr: Address of data buffer
+ * @dir: Channel direction
+ * @bytes_xfer: # of bytes transferred
+ * @transaction_status: Status of last trasnferred

of last transfer

Quoted 76 lines

+ */

include/linux/mhi.h new file +75 -0
+struct mhi_result {
+	void *buf_addr;
+	enum dma_data_direction dir;
+	size_t bytes_xferd;
+	int transaction_status;
+};
+
+/**
+ * struct mhi_driver - mhi driver information
+ * @id_table: NULL terminated channel ID names
+ * @ul_xfer_cb: UL data transfer callback
+ * @dl_xfer_cb: DL data transfer callback
+ * @status_cb: Asynchronous status callback
+ */
+struct mhi_driver {
+	const struct mhi_device_id *id_table;
+	int (*probe)(struct mhi_device *mhi_dev,
+		     const struct mhi_device_id *id);
+	void (*remove)(struct mhi_device *mhi_dev);
+	void (*ul_xfer_cb)(struct mhi_device *mhi_dev,
+			   struct mhi_result *result);
+	void (*dl_xfer_cb)(struct mhi_device *mhi_dev,
+			   struct mhi_result *result);
+	void (*status_cb)(struct mhi_device *mhi_dev, enum MHI_CB mhi_cb);
+	struct device_driver driver;
+};
+
+#define to_mhi_driver(drv) container_of(drv, struct mhi_driver, driver)
+#define to_mhi_device(dev) container_of(dev, struct mhi_device, dev)
+
+static inline void mhi_device_set_devdata(struct mhi_device *mhi_dev,
+					  void *priv)
+{
+	mhi_dev->priv_data = priv;
+}
+
+static inline void *mhi_device_get_devdata(struct mhi_device *mhi_dev)
+{
+	return mhi_dev->priv_data;
+}
+
+static inline void *mhi_controller_get_devdata(struct mhi_controller *mhi_cntrl)
+{
+	return mhi_cntrl->priv_data;
+}
+
+static inline void mhi_free_controller(struct mhi_controller *mhi_cntrl)
+{
+	kfree(mhi_cntrl);
+}
+
+/**
+ * mhi_driver_register - Register driver with MHI framework
+ * @mhi_drv: mhi_driver structure
+ */
+int mhi_driver_register(struct mhi_driver *mhi_drv);
+
+/**
+ * mhi_driver_unregister - Unregister a driver for mhi_devices
+ * @mhi_drv: mhi_driver structure
+ */
+void mhi_driver_unregister(struct mhi_driver *mhi_drv);
+
+/**
+ * mhi_alloc_controller - Allocate mhi_controller structure
+ * Allocate controller structure and additional data for controller
+ * private data. You may get the private data pointer by calling
+ * mhi_controller_get_devdata
+ * @size: # of additional bytes to allocate
+ */
+struct mhi_controller *mhi_alloc_controller(size_t size);
+
+/**
+ * of_register_mhi_controller - Register MHI controller
+ * Registers MHI controller with MHI bus framework. DT must be supported

include/linux/mhi.h line 333

Quoted 10 lines
include/linux/mhi.h new file +10 -0
+ * @mhi_cntrl: MHI controller to register
+ */
+int of_register_mhi_controller(struct mhi_controller *mhi_cntrl);
+
+void mhi_unregister_mhi_controller(struct mhi_controller *mhi_cntrl);
+
+/**
+ * mhi_bdf_to_controller - Look up a registered controller
+ * Search for controller based on device identification
+ * @domain: RC domain of the device

What is an RC domain?

include/linux/mhi.h line 341

Quoted 8 lines

+ * @bus: Bus device connected to
+ * @slot: Slot device assigned to
+ * @dev_id: Device Identification
+ */

include/linux/mhi.h new file +4 -0
+struct mhi_controller *mhi_bdf_to_controller(u32 domain, u32 bus, u32 slot,
+					     u32 dev_id);
+
+#endif /* _MHI_H_ */

thanks,

Signature · 1 line
~Randy
#33 lore raw

PATCH v2 2/7 mhi_bus: core: add power management support

In reply to Sujeev Dias

Add support for MHI power management operations such as power on, off, suspend, and resume.

---
 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
drivers/bus/mhi/core/Makefile +1 -1
index a015809..a6015ab 100644
@@ -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
drivers/bus/mhi/core/mhi_boot.c new file +533 -0

533 lines not on this page · raw message

drivers/bus/mhi/core/mhi_init.c +694 -1

723 lines not on this page · raw message

drivers/bus/mhi/core/mhi_internal.h +491 -0

544 lines not on this page · raw message

drivers/bus/mhi/core/mhi_main.c +527 -1

565 lines not on this page · raw message

drivers/bus/mhi/core/mhi_pm.c new file +1027 -0

633 lines not on this page · raw message

include/linux/mhi.h +121 -0

121 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

Part of the diff is not shown here. View the raw message.

#34 lore raw

PATCH v2 3/7 mhi_bus: core: add support for data transfer

In reply to Sujeev Dias

Add support for transferring data between external modem and MHI host using MHI protocol.

---
 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(-)
drivers/bus/mhi/core/mhi_init.c +75 -1
index 7b3d12a..43a700d 100644
@@ -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 = &mhi_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 = &mhi_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(&mhi_chan->lock);
+
+		/* reset the channel */
+		if (!mhi_chan->offload_ch)
+			mhi_reset_chan(mhi_cntrl, mhi_chan);
 	}
 
 	/* destroy the device */
drivers/bus/mhi/core/mhi_internal.h +0 -8
index 0091245..1167d75 100644
@@ -243,7 +243,6 @@ enum mhi_cmd_type {
 	MHI_CMD_TYPE_RESET = 16,
 	MHI_CMD_TYPE_STOP = 17,
 	MHI_CMD_TYPE_START = 18,
-	MHI_CMD_TYPE_TSYNC = 24,
 };
 
 /* no operation command */
@@ -268,12 +267,6 @@ enum mhi_cmd_type {
 #define MHI_TRE_CMD_START_DWORD1(chid) ((chid << 24) | \
 					(MHI_CMD_TYPE_START << 16))
 
-/* time sync cfg command */
-#define MHI_TRE_CMD_TSYNC_CFG_PTR (0)
-#define MHI_TRE_CMD_TSYNC_CFG_DWORD0 (0)
-#define MHI_TRE_CMD_TSYNC_CFG_DWORD1(er) ((MHI_CMD_TYPE_TSYNC << 16) | \
-					  (er << 24))
-
 #define MHI_TRE_GET_CMD_CHID(tre) (((tre)->dword[1] >> 24) & 0xFF)
 #define MHI_TRE_GET_CMD_TYPE(tre) (((tre)->dword[1] >> 16) & 0xFF)
 
@@ -300,7 +293,6 @@ enum mhi_cmd_type {
 enum MHI_CMD {
 	MHI_CMD_RESET_CHAN,
 	MHI_CMD_START_CHAN,
-	MHI_CMD_TIMSYNC_CFG,
 };
 
 enum MHI_PKT_TYPE {
drivers/bus/mhi/core/mhi_main.c +797 -6

885 lines not on this page · raw message

include/linux/mhi.h +78 -0

96 lines not on this page · raw message

Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#35 lore raw

Re: [PATCH v2 3/7] mhi_bus: core: add support for data transfer

drivers/bus/mhi/core/mhi_main.c int mhi_queue_nop(struct mhi_device *mhi_dev, · line 229

Quoted 8 lines · Sujeev Dias
drivers/bus/mhi/core/mhi_main.c +8 -0
+static void mhi_add_ring_element(struct mhi_controller *mhi_cntrl,
+				 struct mhi_ring *ring)
+{
+	ring->wp += ring->el_size;
+	if (ring->wp >= (ring->base + ring->len))
+		ring->wp = ring->base;
+	/* smp update */
+	smp_wmb();

Why do this? You need to comment the heck out of odd stuff like this.

Also, why are you using your own ring buffer code? What's wrong with the code that is in the kernel already for this type of thing?

thanks,

greg k-h

#36 lore raw

PATCH v2 4/7 mhi_bus: core: add support for handling ioctl cmds

In reply to Sujeev Dias

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.

---
 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
drivers/bus/mhi/core/Makefile +1 -1
index a6015ab..a743fbf 100644
@@ -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
drivers/bus/mhi/core/mhi_dtr.c new file +218 -0

218 lines not on this page · raw message

drivers/bus/mhi/core/mhi_init.c +7 -1
index 43a700d..b09767a 100644
@@ -1293,10 +1293,16 @@ struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl)
 
 static int __init mhi_init(void)
 {
+	int ret;
+
 	/* parent directory */
 	debugfs_create_dir(mhi_bus_type.name, NULL);
 
-	return bus_register(&mhi_bus_type);
+	ret = bus_register(&mhi_bus_type);
+
+	if (!ret)
+		mhi_dtr_init();
+	return ret;
 }
 postcore_initcall(mhi_init);
 
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#37 lore raw

PATCH v2 5/7 mhi_bus: core: add support to get external modem time

In reply to Sujeev Dias

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.

---
 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(-)
Documentation/devicetree/bindings/bus/mhi.txt +7 -0
index 19deb84..1012ff2 100644
@@ -19,6 +19,13 @@ Main node properties:
   Value type: <u32>
   Definition: Maximum timeout in ms wait for state and cmd completion
 
+- mhi,time-sync
+  Usage: optional
+  Value type: <bool>
+  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: <bool>
Documentation/mhi.txt +41 -0

47 lines not on this page · raw message

drivers/bus/mhi/core/mhi_init.c +111 -0

165 lines not on this page · raw message

drivers/bus/mhi/core/mhi_internal.h +56 -1

105 lines not on this page · raw message

drivers/bus/mhi/core/mhi_main.c +257 -6

306 lines not on this page · raw message

drivers/bus/mhi/core/mhi_pm.c +7 -0
index 5220cfa..f3a4965 100644
@@ -415,6 +415,10 @@ static int mhi_pm_amss_transition(struct mhi_controller *mhi_cntrl)
 
 	read_unlock_bh(&mhi_cntrl->pm_lock);
 
+	/* setup support for time sync */
+	if (mhi_cntrl->time_sync)
+		mhi_init_timesync(mhi_cntrl);
+
 	/* add supported devices */
 	mhi_create_devices(mhi_cntrl);
 
@@ -764,6 +768,9 @@ void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful)
 		mhi_deinit_free_irq(mhi_cntrl);
 		mhi_deinit_dev_ctxt(mhi_cntrl);
 	}
+
+	if (mhi_cntrl->mhi_tsync)
+		mhi_cntrl->mhi_tsync->db = NULL;
 }
 EXPORT_SYMBOL(mhi_power_down);
 
include/linux/mhi.h +7 -0
index 308d12b..25de226 100644
@@ -12,6 +12,7 @@
 struct mhi_cmd;
 struct image_info;
 struct bhi_vec_entry;
+struct mhi_timesync;
 struct mhi_buf_info;
 
 /**
@@ -203,6 +204,7 @@ struct mhi_controller {
 	void (*wake_put)(struct mhi_controller *mhi_cntrl, bool override);
 	int (*runtime_get)(struct mhi_controller *mhi_cntrl, void *priv);
 	void (*runtime_put)(struct mhi_controller *mhi_cntrl, void *priv);
+	u64 (*time_get)(struct mhi_controller *mhi_cntrl, void *priv);
 	void (*lpm_disable)(struct mhi_controller *mhi_cntrl, void *priv);
 	void (*lpm_enable)(struct mhi_controller *mhi_cntrl, void *priv);
 	int (*map_single)(struct mhi_controller *mhi_cntrl,
@@ -217,6 +219,11 @@ struct mhi_controller {
 	bool bounce_buf;
 	size_t buffer_len;
 
+	/* supports time sync feature */
+	bool time_sync;
+	struct mhi_timesync *mhi_tsync;
+	struct mhi_device *tsync_dev;
+
 	/* controller specific data */
 	void *priv_data;
 	void *log_buf;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
maintainer
#38 lore raw

Re: [PATCH v2 5/7] mhi_bus: core: add support to get external modem time

Quoted 10 lines · Sujeev Dias

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.

---
 Documentation/devicetree/bindings/bus/mhi.txt |   7 +

Put all the binding in one patch.

Quoted 7 lines
 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(-)
reviewer
#39 lore raw

Re: [PATCH v2 5/7] mhi_bus: core: add support to get external modem time

In reply to Sujeev Dias
Quoted 8 lines · Sujeev Dias

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.

Quoted 10 lines
---
 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(-)

Hi,

More corrections for you...

Documentation/mhi.txt Example Operation for data transfer: · line 142

Quoted 11 lines
Documentation/mhi.txt +3 -0
index 1c501f1..9287899 100644
@@ -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

provides

Quoted 12 lines
Documentation/mhi.txt +12 -0
+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

Documentation/mhi.txt Example Operation for data transfer: · line 164

Quoted 10 lines
Documentation/mhi.txt +10 -0
+Modem Time: Ty
+
+Client request time @ time T2
+Host Time: Txx
+Modem Time: Tyy
+
+Then drift is:
+Tyy - Ty + <drift> == Txx - Tx
+
+Clients are free to implement their own drift algorithms, what MHI host provide

algorithms. What MHI host provides

Documentation/mhi.txt Example Operation for data transfer: · line 174

Quoted 10 lines
Documentation/mhi.txt +10 -0
+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.

It's important that the time between Step 1 and Step 2 is as deterministic as possible.

Quoted 15 lines
Documentation/mhi.txt +6 -0
+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
 ----------
 
drivers/bus/mhi/core/mhi_internal.h +0 -0
index 1167d75..47d258a 100644

drivers/bus/mhi/core/mhi_internal.h line 129

Quoted 2 lines
drivers/bus/mhi/core/mhi_internal.h +0 -0
@@ -128,6 +128,30 @@
 #define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_MASK (0xFFFFFFFF)
 #define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_SHIFT (0)

ugh. Way too long for a name.

Quoted 89 lines
drivers/bus/mhi/core/mhi_main.c +70 -0
index 3e7077a8..8a0a7e1 100644
@@ -53,6 +53,40 @@ int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl,
 	return 0;
 }
 
+int mhi_get_capability_offset(struct mhi_controller *mhi_cntrl,
+			      u32 capability,
+			      u32 *offset)
+{
+	u32 cur_cap, next_offset;
+	int ret;
+
+	/* get the 1st supported capability offset */
+	ret = mhi_read_reg_field(mhi_cntrl, mhi_cntrl->regs, MISC_OFFSET,
+				 MISC_CAP_MASK, MISC_CAP_SHIFT, offset);
+	if (ret)
+		return ret;
+	do {
+		ret = mhi_read_reg_field(mhi_cntrl, mhi_cntrl->regs, *offset,
+					 CAP_CAPID_MASK, CAP_CAPID_SHIFT,
+					 &cur_cap);
+		if (ret)
+			return ret;
+
+		if (cur_cap == capability)
+			return 0;
+
+		ret = mhi_read_reg_field(mhi_cntrl, mhi_cntrl->regs, *offset,
+					 CAP_NEXT_CAP_MASK, CAP_NEXT_CAP_SHIFT,
+					 &next_offset);
+		if (ret)
+			return ret;
+
+		*offset += next_offset;
+	} while (next_offset);
+
+	return -ENXIO;
+}
+
 void mhi_write_reg(struct mhi_controller *mhi_cntrl,
 		   void __iomem *base,
 		   u32 offset,
@@ -547,6 +581,42 @@ static void mhi_assign_of_node(struct mhi_controller *mhi_cntrl,
 	}
 }
 
+static void mhi_create_time_sync_dev(struct mhi_controller *mhi_cntrl)
+{
+	struct mhi_device *mhi_dev;
+	struct mhi_timesync *mhi_tsync = mhi_cntrl->mhi_tsync;
+	int ret;
+
+	if (!mhi_tsync || !mhi_tsync->db)
+		return;
+
+	if (mhi_cntrl->ee != MHI_EE_AMSS)
+		return;
+
+	mhi_dev = mhi_alloc_device(mhi_cntrl);
+	if (!mhi_dev)
+		return;
+
+	mhi_dev->dev_type = MHI_TIMESYNC_TYPE;
+	mhi_dev->chan_name = "TIME_SYNC";
+	dev_set_name(&mhi_dev->dev, "%04x_%02u.%02u.%02u_%s", mhi_dev->dev_id,
+		     mhi_dev->domain, mhi_dev->bus, mhi_dev->slot,
+		     mhi_dev->chan_name);
+
+	/* add if there is a matching DT node */
+	mhi_assign_of_node(mhi_cntrl, mhi_dev);
+
+	ret = device_add(&mhi_dev->dev);
+	if (ret) {
+		dev_err(mhi_cntrl->dev, "Failed to register dev for  chan:%s\n",
+			mhi_dev->chan_name);
+		mhi_dealloc_device(mhi_cntrl, mhi_dev);
+		return;
+	}
+
+	mhi_cntrl->tsync_dev = mhi_dev;
+}
+
 /* bind mhi channels into mhi devices */
 void mhi_create_devices(struct mhi_controller *mhi_cntrl)
 {

drivers/bus/mhi/core/mhi_main.c void mhi_create_devices(struct mhi_controller *mhi_cntrl) · line 631

Quoted 7 lines
drivers/bus/mhi/core/mhi_main.c +4 -0
@@ -555,6 +625,13 @@ void mhi_create_devices(struct mhi_controller *mhi_cntrl)
 	struct mhi_device *mhi_dev;
 	int ret;
 
+	/*
+	 * we need to create time sync device before creating other
+	 * devices, because client may try to capture time during
+	 * clint probe.

client

Quoted 154 lines
drivers/bus/mhi/core/mhi_main.c +116 -6
+	 */
+	mhi_create_time_sync_dev(mhi_cntrl);
+
 	mhi_chan = mhi_cntrl->mhi_chan;
 	for (i = 0; i < mhi_cntrl->max_chan; i++, mhi_chan++) {
 		if (!mhi_chan->configured || mhi_chan->ee != mhi_cntrl->ee)
@@ -753,16 +830,26 @@ static void mhi_process_cmd_completion(struct mhi_controller *mhi_cntrl,
 	struct mhi_ring *mhi_ring = &cmd_ring->ring;
 	struct mhi_tre *cmd_pkt;
 	struct mhi_chan *mhi_chan;
+	struct mhi_timesync *mhi_tsync;
+	enum mhi_cmd_type type;
 	u32 chan;
 
 	cmd_pkt = mhi_to_virtual(mhi_ring, ptr);
 
-	chan = MHI_TRE_GET_CMD_CHID(cmd_pkt);
-	mhi_chan = &mhi_cntrl->mhi_chan[chan];
-	write_lock_bh(&mhi_chan->lock);
-	mhi_chan->ccs = MHI_TRE_GET_EV_CODE(tre);
-	complete(&mhi_chan->completion);
-	write_unlock_bh(&mhi_chan->lock);
+	type = MHI_TRE_GET_CMD_TYPE(cmd_pkt);
+
+	if (type == MHI_CMD_TYPE_TSYNC) {
+		mhi_tsync = mhi_cntrl->mhi_tsync;
+		mhi_tsync->ccs = MHI_TRE_GET_EV_CODE(tre);
+		complete(&mhi_tsync->completion);
+	} else {
+		chan = MHI_TRE_GET_CMD_CHID(cmd_pkt);
+		mhi_chan = &mhi_cntrl->mhi_chan[chan];
+		write_lock_bh(&mhi_chan->lock);
+		mhi_chan->ccs = MHI_TRE_GET_EV_CODE(tre);
+		complete(&mhi_chan->completion);
+		write_unlock_bh(&mhi_chan->lock);
+	}
 
 	mhi_del_ring_element(mhi_cntrl, mhi_ring);
 }
@@ -929,6 +1016,73 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl,
 	return count;
 }
 
+int mhi_process_tsync_event_ring(struct mhi_controller *mhi_cntrl,
+				 struct mhi_event *mhi_event,
+				 u32 event_quota)
+{
+	struct mhi_tre *dev_rp, *local_rp;
+	struct mhi_ring *ev_ring = &mhi_event->ring;
+	struct mhi_event_ctxt *er_ctxt =
+		&mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
+	struct mhi_timesync *mhi_tsync = mhi_cntrl->mhi_tsync;
+	int count = 0;
+	u32 sequence;
+	u64 remote_time;
+
+	if (unlikely(MHI_EVENT_ACCESS_INVALID(mhi_cntrl->pm_state))) {
+		read_unlock_bh(&mhi_cntrl->pm_lock);
+		return -EIO;
+	}
+
+	dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp);
+	local_rp = ev_ring->rp;
+
+	while (dev_rp != local_rp) {
+		struct tsync_node *tsync_node;
+
+		sequence = MHI_TRE_GET_EV_SEQ(local_rp);
+		remote_time = MHI_TRE_GET_EV_TIME(local_rp);
+
+		do {
+			spin_lock_irq(&mhi_tsync->lock);
+			tsync_node = list_first_entry_or_null(&mhi_tsync->head,
+						      struct tsync_node, node);
+
+			if (unlikely(!tsync_node))
+				break;
+
+			list_del(&tsync_node->node);
+			spin_unlock_irq(&mhi_tsync->lock);
+
+			/*
+			 * device may not able to process all time sync commands
+			 * host issue and only process last command it receive
+			 */
+			if (tsync_node->sequence == sequence) {
+				tsync_node->cb_func(tsync_node->mhi_dev,
+						    sequence,
+						    tsync_node->local_time,
+						    remote_time);
+				kfree(tsync_node);
+			} else {
+				kfree(tsync_node);
+			}
+		} while (true);
+
+		mhi_recycle_ev_ring_element(mhi_cntrl, ev_ring);
+		local_rp = ev_ring->rp;
+		dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp);
+		count++;
+	}
+
+	read_lock_bh(&mhi_cntrl->pm_lock);
+	if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state)))
+		mhi_ring_er_db(mhi_event);
+	read_unlock_bh(&mhi_cntrl->pm_lock);
+
+	return count;
+}
+
 void mhi_ev_task(unsigned long data)
 {
 	struct mhi_event *mhi_event = (struct mhi_event *)data;
@@ -1060,6 +1214,12 @@ int mhi_send_cmd(struct mhi_controller *mhi_cntrl,
 		cmd_tre->dword[0] = MHI_TRE_CMD_START_DWORD0;
 		cmd_tre->dword[1] = MHI_TRE_CMD_START_DWORD1(chan);
 		break;
+	case MHI_CMD_TIMSYNC_CFG:
+		cmd_tre->ptr = MHI_TRE_CMD_TSYNC_CFG_PTR;
+		cmd_tre->dword[0] = MHI_TRE_CMD_TSYNC_CFG_DWORD0;
+		cmd_tre->dword[1] = MHI_TRE_CMD_TSYNC_CFG_DWORD1
+			(mhi_cntrl->mhi_tsync->er_index);
+		break;
 	}
 
 	/* queue to hardware */
@@ -1437,3 +1597,94 @@ int mhi_poll(struct mhi_device *mhi_dev,
 	return ret;
 }
 EXPORT_SYMBOL(mhi_poll);
+
+/**
+ * mhi_get_remote_time - Get external modem time relative to host time
+ * Trigger event to capture modem time, also capture host time so client
+ * can do a relative drift comparision.
+ * Recommended only tsync device calls this method and do not call this
+ * from atomic context
+ * @mhi_dev: Device associated with the channels
+ * @sequence:unique sequence id track event
+ * @cb_func: callback function to call back
+ */
+int mhi_get_remote_time(struct mhi_device *mhi_dev,
+			u32 sequence,
+			void (*cb_func)(struct mhi_device *mhi_dev,
+					u32 sequence,
+					u64 local_time,
+					u64 remote_time))
+{
+	struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
+	struct mhi_timesync *mhi_tsync = mhi_cntrl->mhi_tsync;
+	struct tsync_node *tsync_node;
+	int ret;
+
+	/* not all devices support time feature */

drivers/bus/mhi/core/mhi_main.c int mhi_poll(struct mhi_device *mhi_dev, · line 1633

Quoted 10 lines
drivers/bus/mhi/core/mhi_main.c +10 -0
+	if (!mhi_tsync)
+		return -EIO;
+
+	/* tsync db can only be rung in M0 state */
+	ret = __mhi_device_get_sync(mhi_cntrl);
+	if (ret)
+		return ret;
+
+	/*
+	 * technically we can use GFP_KERNEL, but wants to avoid

want

Quoted 2 lines
drivers/bus/mhi/core/mhi_main.c +2 -0
+	 * # of times scheduling out
+	 */
Signature · 1 line
~Randy
#40 lore raw

PATCH v2 6/7 mhi_bus: controller: MHI support for QCOM modems

In reply to Sujeev Dias

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.

---
 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
Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +58 -0
new file mode 100644
index 0000000..0a48a50
@@ -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 <u32>
+  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: <u32>
+  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 <u64>
+  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 */
+&pcie1 {
+	/* 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 0x20000000 0x0 0x3fffffff>;
+
+			<mhi bus configurations>
+		};
+	};
+};
arch/arm64/configs/defconfig +1 -0
index 3562026..fd36426 100644
@@ -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
drivers/bus/Kconfig +1 -0
index 080d3c2..8c6827a 100644
@@ -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
drivers/bus/mhi/Makefile +1 -0
index f8f14f7..3458ba3 100644
@@ -4,3 +4,4 @@
 
 # core layer
 obj-y += core/
+obj-y += controllers/
\ No newline at end of file
drivers/bus/mhi/controllers/Kconfig new file +13 -0
new file mode 100644
index 0000000..2586cc4
@@ -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
drivers/bus/mhi/controllers/Makefile new file +1 -0
new file mode 100644
index 0000000..292f696
@@ -0,0 +1 @@
+obj-$(CONFIG_MHI_QCOM) += mhi_qcom.o
drivers/bus/mhi/controllers/mhi_qcom.c new file +461 -0

461 lines not on this page · raw message

drivers/bus/mhi/controllers/mhi_qcom.h new file +67 -0

67 lines not on this page · raw message

Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
maintainer
#41 lore raw

Re: [PATCH v2 6/7] mhi_bus: controller: MHI support for QCOM modems

Quoted 10 lines · Sujeev Dias

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.

---
 Documentation/devicetree/bindings/bus/mhi_qcom.txt |  58 +++

And this one in it's own patch.

Quoted 28 lines
 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
Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +8 -0
new file mode 100644
index 0000000..0a48a50
@@ -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
+==============

Documentation/devicetree/bindings/bus/mhi_qcom.txt line 18

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +10 -0
+
+Main node properties:
+
+- reg
+  Usage: required
+  Value type: Array (5-cell PCI resource) of <u32>
+  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

This should probably be part of the SMMU binding?

Quoted 23 lines
Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +23 -0
+  Usage: required
+  Value type: <u32>
+  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 <u64>
+  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:

Documentation/devicetree/bindings/bus/mhi_qcom.txt line 51

Quoted 10 lines
Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +10 -0
+========
+
+/* pcie domain (root complex) modem connected to */
+&pcie1 {
+	/* pcie bus modem connected to */
+	pci,bus@1 {
+		reg = <0 0 0 0 0>;
+
+		qcom,mhi {
+			reg = <0 0 0 0 0>;

2 levels of PCI addresses doesn't look right, but I can't really tell in your example. The addresses don't look valid.

Quoted 7 lines
Documentation/devicetree/bindings/bus/mhi_qcom.txt new file +7 -0
+			qcom,smmu-cfg = <0x3d>;
+			qcom,addr-win = <0x0 0x20000000 0x0 0x3fffffff>;
+
+			<mhi bus configurations>
+		};
+	};
+};
#42 lore raw

PATCH v2 7/7 mhi_bus: dev: uci: add user space interface driver

In reply to Sujeev Dias

This module allows user space clients to transfer data between external modem and host using standard file operations.

---
 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
arch/arm64/configs/defconfig +1 -0
index fd36426..7f68d706 100644
@@ -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
drivers/bus/Kconfig +1 -0
index 8c6827a..cb10366 100644
@@ -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
drivers/bus/mhi/Makefile +2 -1
index 3458ba3..2382e04 100644
@@ -4,4 +4,5 @@
 
 # core layer
 obj-y += core/
-obj-y += controllers/
\ No newline at end of file
+obj-y += controllers/
+obj-y += devices/
drivers/bus/mhi/devices/Kconfig new file +13 -0
new file mode 100644
index 0000000..45cd742
@@ -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
drivers/bus/mhi/devices/Makefile new file +1 -0
new file mode 100644
index 0000000..ddc0613
@@ -0,0 +1 @@
+obj-$(CONFIG_MHI_UCI) +=mhi_uci.o
drivers/bus/mhi/devices/mhi_uci.c new file +590 -0

590 lines not on this page · raw message

Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#43 lore raw

Re: MHI code review

In reply to Sujeev Dias

Hi Sujeev,

Quoted 6 lines

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.

Quoted 6 lines

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

#44 lore raw

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 <[email protected]>
Sent: Tuesday, April 30, 2019 8:11 AM
To: [email protected]
Cc: [email protected]; [email protected]; [email protected]
Subject: Re: MHI code review

Hi Sujeev,

Quoted 6 lines

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.

Quoted 6 lines

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

#45 lore raw

Re: MHI code review

Hi Sujeev,

Il giorno mer 12 giu 2019 alle ore 19:54 Sujeev Dias <[email protected]> ha scritto:

Quoted 8 lines

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.

great, thanks for the update! I'll wait for you new patch-set.

Thanks,
Daniele

Quoted 35 lines

Thanks
Sujeev

-----Original Message-----
From: Daniele Palmas <[email protected]>
Sent: Tuesday, April 30, 2019 8:11 AM
To: [email protected]
Cc: [email protected]; [email protected]; [email protected]
Subject: Re: MHI code review

Hi Sujeev,

Quoted 6 lines

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.

Quoted 6 lines

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

#46 lore raw

RE: MHI code review

In reply to Daniele Palmas

Our team also monitoring following thread
https://lkml.kernel.org/lkml/[email protected]/

Since this also has implication on MHI as well.

Thanks
Sujeev

-----Original Message-----
From: Sujeev Dias <[email protected]>
Sent: Wednesday, June 12, 2019 10:55 AM
To: 'Daniele Palmas' <[email protected]>
Cc: '[email protected]' <[email protected]>; '[email protected]' <[email protected]>
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 <[email protected]>
Sent: Tuesday, April 30, 2019 8:11 AM
To: [email protected]
Cc: [email protected]; [email protected]; [email protected]
Subject: Re: MHI code review

Hi Sujeev,

Quoted 6 lines

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.

Quoted 6 lines

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