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

2018-04-27 Thread kbuild test robot
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 infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


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

2018-04-27 Thread kbuild test robot
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 infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


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

2018-04-27 Thread kbuild test robot
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", 

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

2018-04-27 Thread kbuild test robot
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", 

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

2018-04-27 Thread Arnd Bergmann
On Fri, Apr 27, 2018 at 4:23 AM, Sujeev Dias  wrote:
> This module allows user space clients to transfer data
> between external modem and host using standard file
> operations.
>
> Signed-off-by: Sujeev Dias 
> ---
>  drivers/bus/mhi/devices/Kconfig   |   9 +
>  drivers/bus/mhi/devices/Makefile  |   1 +
>  drivers/bus/mhi/devices/mhi_uci.c | 662 
> ++
>  3 files changed, 672 insertions(+)
>  create mode 100644 drivers/bus/mhi/devices/mhi_uci.c
>
> diff --git a/drivers/bus/mhi/devices/Kconfig b/drivers/bus/mhi/devices/Kconfig
> index 40f964d..83b9673 100644
> --- a/drivers/bus/mhi/devices/Kconfig
> +++ b/drivers/bus/mhi/devices/Kconfig
> @@ -7,4 +7,13 @@ config MHI_NETDEV
>   MHI based net device driver for transferring IP traffic
>   between host and modem. By enabling this driver, clients
>   can transfer data using standard network interface.
> +
> +config MHI_UCI
> +   tristate "MHI UCI"
> +   depends on MHI_BUS
> +   help
> + MHI based uci driver is for transferring data between host and
> + modem using standard file operations from user space. Open, read,
> + write, ioctl, and close operations are supported by this driver.
> +

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


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

2018-04-27 Thread Arnd Bergmann
On Fri, Apr 27, 2018 at 4:23 AM, Sujeev Dias  wrote:
> This module allows user space clients to transfer data
> between external modem and host using standard file
> operations.
>
> Signed-off-by: Sujeev Dias 
> ---
>  drivers/bus/mhi/devices/Kconfig   |   9 +
>  drivers/bus/mhi/devices/Makefile  |   1 +
>  drivers/bus/mhi/devices/mhi_uci.c | 662 
> ++
>  3 files changed, 672 insertions(+)
>  create mode 100644 drivers/bus/mhi/devices/mhi_uci.c
>
> diff --git a/drivers/bus/mhi/devices/Kconfig b/drivers/bus/mhi/devices/Kconfig
> index 40f964d..83b9673 100644
> --- a/drivers/bus/mhi/devices/Kconfig
> +++ b/drivers/bus/mhi/devices/Kconfig
> @@ -7,4 +7,13 @@ config MHI_NETDEV
>   MHI based net device driver for transferring IP traffic
>   between host and modem. By enabling this driver, clients
>   can transfer data using standard network interface.
> +
> +config MHI_UCI
> +   tristate "MHI UCI"
> +   depends on MHI_BUS
> +   help
> + MHI based uci driver is for transferring data between host and
> + modem using standard file operations from user space. Open, read,
> + write, ioctl, and close operations are supported by this driver.
> +

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


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

2018-04-26 Thread Sujeev Dias
This module allows user space clients to transfer data
between external modem and host using standard file
operations.

Signed-off-by: Sujeev Dias 
---
 drivers/bus/mhi/devices/Kconfig   |   9 +
 drivers/bus/mhi/devices/Makefile  |   1 +
 drivers/bus/mhi/devices/mhi_uci.c | 662 ++
 3 files changed, 672 insertions(+)
 create mode 100644 drivers/bus/mhi/devices/mhi_uci.c

diff --git a/drivers/bus/mhi/devices/Kconfig b/drivers/bus/mhi/devices/Kconfig
index 40f964d..83b9673 100644
--- a/drivers/bus/mhi/devices/Kconfig
+++ b/drivers/bus/mhi/devices/Kconfig
@@ -7,4 +7,13 @@ config MHI_NETDEV
  MHI based net device driver for transferring IP traffic
  between host and modem. By enabling this driver, clients
  can transfer data using standard network interface.
+
+config MHI_UCI
+   tristate "MHI UCI"
+   depends on MHI_BUS
+   help
+ MHI based uci driver is for transferring data between host and
+ modem using standard file operations from user space. Open, read,
+ write, ioctl, and close operations are supported by this driver.
+
 endmenu
diff --git a/drivers/bus/mhi/devices/Makefile b/drivers/bus/mhi/devices/Makefile
index ee12a64..300eed1 100644
--- a/drivers/bus/mhi/devices/Makefile
+++ b/drivers/bus/mhi/devices/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_MHI_NETDEV) +=mhi_netdev.o
+obj-$(CONFIG_MHI_UCI) +=mhi_uci.o
diff --git a/drivers/bus/mhi/devices/mhi_uci.c 
b/drivers/bus/mhi/devices/mhi_uci.c
new file mode 100644
index 000..11b7b1f
--- /dev/null
+++ b/drivers/bus/mhi/devices/mhi_uci.c
@@ -0,0 +1,662 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEVICE_NAME "mhi"
+#define MHI_UCI_DRIVER_NAME "mhi_uci"
+
+struct uci_chan {
+   wait_queue_head_t wq;
+   spinlock_t lock;
+   struct list_head pending; /* user space waiting to read */
+   struct uci_buf *cur_buf; /* current buffer user space reading */
+   size_t rx_size;
+};
+
+struct uci_buf {
+   void *data;
+   size_t len;
+   struct list_head node;
+};
+
+struct uci_dev {
+   struct list_head node;
+   dev_t devt;
+   struct device *dev;
+   struct mhi_device *mhi_dev;
+   const char *chan;
+   struct mutex mutex; /* sync open and close */
+   struct uci_chan ul_chan;
+   struct uci_chan dl_chan;
+   size_t mtu;
+   int ref_count;
+   bool enabled;
+};
+
+struct mhi_uci_drv {
+   struct list_head head;
+   struct mutex lock;
+   struct class *class;
+   int major;
+   dev_t dev_t;
+};
+
+enum MHI_DEBUG_LEVEL msg_lvl = MHI_MSG_LVL_ERROR;
+
+#ifdef CONFIG_MHI_DEBUG
+
+#define MSG_VERB(fmt, ...) do { \
+   if (msg_lvl <= MHI_MSG_LVL_VERBOSE) \
+   pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \
+   } while (0)
+
+#else
+
+#define MSG_VERB(fmt, ...)
+
+#endif
+
+#define MSG_LOG(fmt, ...) do { \
+   if (msg_lvl <= MHI_MSG_LVL_INFO) \
+   pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__); \
+   } while (0)
+
+#define MSG_ERR(fmt, ...) do { \
+   if (msg_lvl <= MHI_MSG_LVL_ERROR) \
+   pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \
+   } while (0)
+
+#define MAX_UCI_DEVICES (64)
+
+static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES);
+static struct mhi_uci_drv mhi_uci_drv;
+
+static int mhi_queue_inbound(struct uci_dev *uci_dev)
+{
+   struct mhi_device *mhi_dev = uci_dev->mhi_dev;
+   int nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE);
+   size_t mtu = uci_dev->mtu;
+   void *buf;
+   struct uci_buf *uci_buf;
+   int ret = -EIO, i;
+
+   for (i = 0; i < nr_trbs; i++) {
+   buf = kmalloc(mtu + sizeof(*uci_buf), GFP_KERNEL);
+   if (!buf)
+   return -ENOMEM;
+
+   uci_buf = buf + mtu;
+   uci_buf->data = buf;
+
+   MSG_VERB("Allocated buf %d of %d size %ld\n", i, nr_trbs, mtu);
+
+   ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf, mtu,
+MHI_EOT);
+   if (ret) {
+   kfree(buf);
+   MSG_ERR("Failed to queue buffer %d\n", i);
+   return ret;
+ 

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

2018-04-26 Thread Sujeev Dias
This module allows user space clients to transfer data
between external modem and host using standard file
operations.

Signed-off-by: Sujeev Dias 
---
 drivers/bus/mhi/devices/Kconfig   |   9 +
 drivers/bus/mhi/devices/Makefile  |   1 +
 drivers/bus/mhi/devices/mhi_uci.c | 662 ++
 3 files changed, 672 insertions(+)
 create mode 100644 drivers/bus/mhi/devices/mhi_uci.c

diff --git a/drivers/bus/mhi/devices/Kconfig b/drivers/bus/mhi/devices/Kconfig
index 40f964d..83b9673 100644
--- a/drivers/bus/mhi/devices/Kconfig
+++ b/drivers/bus/mhi/devices/Kconfig
@@ -7,4 +7,13 @@ config MHI_NETDEV
  MHI based net device driver for transferring IP traffic
  between host and modem. By enabling this driver, clients
  can transfer data using standard network interface.
+
+config MHI_UCI
+   tristate "MHI UCI"
+   depends on MHI_BUS
+   help
+ MHI based uci driver is for transferring data between host and
+ modem using standard file operations from user space. Open, read,
+ write, ioctl, and close operations are supported by this driver.
+
 endmenu
diff --git a/drivers/bus/mhi/devices/Makefile b/drivers/bus/mhi/devices/Makefile
index ee12a64..300eed1 100644
--- a/drivers/bus/mhi/devices/Makefile
+++ b/drivers/bus/mhi/devices/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_MHI_NETDEV) +=mhi_netdev.o
+obj-$(CONFIG_MHI_UCI) +=mhi_uci.o
diff --git a/drivers/bus/mhi/devices/mhi_uci.c 
b/drivers/bus/mhi/devices/mhi_uci.c
new file mode 100644
index 000..11b7b1f
--- /dev/null
+++ b/drivers/bus/mhi/devices/mhi_uci.c
@@ -0,0 +1,662 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEVICE_NAME "mhi"
+#define MHI_UCI_DRIVER_NAME "mhi_uci"
+
+struct uci_chan {
+   wait_queue_head_t wq;
+   spinlock_t lock;
+   struct list_head pending; /* user space waiting to read */
+   struct uci_buf *cur_buf; /* current buffer user space reading */
+   size_t rx_size;
+};
+
+struct uci_buf {
+   void *data;
+   size_t len;
+   struct list_head node;
+};
+
+struct uci_dev {
+   struct list_head node;
+   dev_t devt;
+   struct device *dev;
+   struct mhi_device *mhi_dev;
+   const char *chan;
+   struct mutex mutex; /* sync open and close */
+   struct uci_chan ul_chan;
+   struct uci_chan dl_chan;
+   size_t mtu;
+   int ref_count;
+   bool enabled;
+};
+
+struct mhi_uci_drv {
+   struct list_head head;
+   struct mutex lock;
+   struct class *class;
+   int major;
+   dev_t dev_t;
+};
+
+enum MHI_DEBUG_LEVEL msg_lvl = MHI_MSG_LVL_ERROR;
+
+#ifdef CONFIG_MHI_DEBUG
+
+#define MSG_VERB(fmt, ...) do { \
+   if (msg_lvl <= MHI_MSG_LVL_VERBOSE) \
+   pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \
+   } while (0)
+
+#else
+
+#define MSG_VERB(fmt, ...)
+
+#endif
+
+#define MSG_LOG(fmt, ...) do { \
+   if (msg_lvl <= MHI_MSG_LVL_INFO) \
+   pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__); \
+   } while (0)
+
+#define MSG_ERR(fmt, ...) do { \
+   if (msg_lvl <= MHI_MSG_LVL_ERROR) \
+   pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \
+   } while (0)
+
+#define MAX_UCI_DEVICES (64)
+
+static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES);
+static struct mhi_uci_drv mhi_uci_drv;
+
+static int mhi_queue_inbound(struct uci_dev *uci_dev)
+{
+   struct mhi_device *mhi_dev = uci_dev->mhi_dev;
+   int nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE);
+   size_t mtu = uci_dev->mtu;
+   void *buf;
+   struct uci_buf *uci_buf;
+   int ret = -EIO, i;
+
+   for (i = 0; i < nr_trbs; i++) {
+   buf = kmalloc(mtu + sizeof(*uci_buf), GFP_KERNEL);
+   if (!buf)
+   return -ENOMEM;
+
+   uci_buf = buf + mtu;
+   uci_buf->data = buf;
+
+   MSG_VERB("Allocated buf %d of %d size %ld\n", i, nr_trbs, mtu);
+
+   ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf, mtu,
+MHI_EOT);
+   if (ret) {
+   kfree(buf);
+   MSG_ERR("Failed to queue buffer %d\n", i);
+   return ret;
+   }
+   }