All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 01/26] staging: most: rearrange source files
@ 2017-10-13 14:32 Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 02/26] staging: most: integrate driver in kernel's device model Christian Gromm
                   ` (25 more replies)
  0 siblings, 26 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: driverdev-devel, Christian Gromm

This patch renames and moves the source files of the driver. Additionally,
it adapts the ABI, Makefiles and Kconfig files of the kernel's build
system.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 .../most/Documentation/ABI/sysfs-bus-most.txt      |  313 ++++
 drivers/staging/most/Kconfig                       |   27 +-
 drivers/staging/most/Makefile                      |   19 +-
 drivers/staging/most/aim-cdev/Kconfig              |   12 -
 drivers/staging/most/aim-cdev/Makefile             |    4 -
 drivers/staging/most/aim-cdev/cdev.c               |  564 ------
 drivers/staging/most/aim-network/Kconfig           |   13 -
 drivers/staging/most/aim-network/Makefile          |    4 -
 drivers/staging/most/aim-network/networking.c      |  567 ------
 drivers/staging/most/aim-sound/Kconfig             |   13 -
 drivers/staging/most/aim-sound/Makefile            |    4 -
 drivers/staging/most/aim-sound/sound.c             |  765 --------
 drivers/staging/most/aim-v4l2/Kconfig              |   12 -
 drivers/staging/most/aim-v4l2/Makefile             |    5 -
 drivers/staging/most/aim-v4l2/video.c              |  616 -------
 drivers/staging/most/cdev/Kconfig                  |   12 +
 drivers/staging/most/cdev/Makefile                 |    4 +
 drivers/staging/most/cdev/cdev.c                   |  564 ++++++
 drivers/staging/most/core.c                        | 1949 ++++++++++++++++++++
 drivers/staging/most/core.h                        |  325 ++++
 drivers/staging/most/dim2/Kconfig                  |   16 +
 drivers/staging/most/dim2/Makefile                 |    4 +
 drivers/staging/most/dim2/dim2.c                   |  918 +++++++++
 drivers/staging/most/dim2/dim2.h                   |   27 +
 drivers/staging/most/dim2/errors.h                 |   57 +
 drivers/staging/most/dim2/hal.c                    |  985 ++++++++++
 drivers/staging/most/dim2/hal.h                    |  112 ++
 drivers/staging/most/dim2/reg.h                    |  163 ++
 drivers/staging/most/dim2/sysfs.c                  |  115 ++
 drivers/staging/most/dim2/sysfs.h                  |   36 +
 drivers/staging/most/hdm-dim2/Kconfig              |   16 -
 drivers/staging/most/hdm-dim2/Makefile             |    5 -
 drivers/staging/most/hdm-dim2/dim2_errors.h        |   57 -
 drivers/staging/most/hdm-dim2/dim2_hal.c           |  985 ----------
 drivers/staging/most/hdm-dim2/dim2_hal.h           |  112 --
 drivers/staging/most/hdm-dim2/dim2_hdm.c           |  918 ---------
 drivers/staging/most/hdm-dim2/dim2_hdm.h           |   27 -
 drivers/staging/most/hdm-dim2/dim2_reg.h           |  163 --
 drivers/staging/most/hdm-dim2/dim2_sysfs.c         |  115 --
 drivers/staging/most/hdm-dim2/dim2_sysfs.h         |   36 -
 drivers/staging/most/hdm-i2c/Kconfig               |   12 -
 drivers/staging/most/hdm-i2c/Makefile              |    3 -
 drivers/staging/most/hdm-i2c/hdm_i2c.c             |  423 -----
 drivers/staging/most/hdm-usb/Kconfig               |   14 -
 drivers/staging/most/hdm-usb/Makefile              |    4 -
 drivers/staging/most/hdm-usb/hdm_usb.c             | 1307 -------------
 drivers/staging/most/i2c/Kconfig                   |   12 +
 drivers/staging/most/i2c/Makefile                  |    4 +
 drivers/staging/most/i2c/i2c.c                     |  423 +++++
 drivers/staging/most/mostcore/Kconfig              |   14 -
 drivers/staging/most/mostcore/Makefile             |    3 -
 drivers/staging/most/mostcore/core.c               | 1949 --------------------
 drivers/staging/most/mostcore/mostcore.h           |  325 ----
 drivers/staging/most/net/Kconfig                   |   13 +
 drivers/staging/most/net/Makefile                  |    4 +
 drivers/staging/most/net/net.c                     |  567 ++++++
 drivers/staging/most/sound/Kconfig                 |   13 +
 drivers/staging/most/sound/Makefile                |    4 +
 drivers/staging/most/sound/sound.c                 |  765 ++++++++
 drivers/staging/most/usb/Kconfig                   |   13 +
 drivers/staging/most/usb/Makefile                  |    4 +
 drivers/staging/most/usb/usb.c                     | 1307 +++++++++++++
 drivers/staging/most/video/Kconfig                 |   12 +
 drivers/staging/most/video/Makefile                |    4 +
 drivers/staging/most/video/video.c                 |  616 +++++++
 65 files changed, 9387 insertions(+), 9087 deletions(-)
 create mode 100644 drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt
 delete mode 100644 drivers/staging/most/aim-cdev/Kconfig
 delete mode 100644 drivers/staging/most/aim-cdev/Makefile
 delete mode 100644 drivers/staging/most/aim-cdev/cdev.c
 delete mode 100644 drivers/staging/most/aim-network/Kconfig
 delete mode 100644 drivers/staging/most/aim-network/Makefile
 delete mode 100644 drivers/staging/most/aim-network/networking.c
 delete mode 100644 drivers/staging/most/aim-sound/Kconfig
 delete mode 100644 drivers/staging/most/aim-sound/Makefile
 delete mode 100644 drivers/staging/most/aim-sound/sound.c
 delete mode 100644 drivers/staging/most/aim-v4l2/Kconfig
 delete mode 100644 drivers/staging/most/aim-v4l2/Makefile
 delete mode 100644 drivers/staging/most/aim-v4l2/video.c
 create mode 100644 drivers/staging/most/cdev/Kconfig
 create mode 100644 drivers/staging/most/cdev/Makefile
 create mode 100644 drivers/staging/most/cdev/cdev.c
 create mode 100644 drivers/staging/most/core.c
 create mode 100644 drivers/staging/most/core.h
 create mode 100644 drivers/staging/most/dim2/Kconfig
 create mode 100644 drivers/staging/most/dim2/Makefile
 create mode 100644 drivers/staging/most/dim2/dim2.c
 create mode 100644 drivers/staging/most/dim2/dim2.h
 create mode 100644 drivers/staging/most/dim2/errors.h
 create mode 100644 drivers/staging/most/dim2/hal.c
 create mode 100644 drivers/staging/most/dim2/hal.h
 create mode 100644 drivers/staging/most/dim2/reg.h
 create mode 100644 drivers/staging/most/dim2/sysfs.c
 create mode 100644 drivers/staging/most/dim2/sysfs.h
 delete mode 100644 drivers/staging/most/hdm-dim2/Kconfig
 delete mode 100644 drivers/staging/most/hdm-dim2/Makefile
 delete mode 100644 drivers/staging/most/hdm-dim2/dim2_errors.h
 delete mode 100644 drivers/staging/most/hdm-dim2/dim2_hal.c
 delete mode 100644 drivers/staging/most/hdm-dim2/dim2_hal.h
 delete mode 100644 drivers/staging/most/hdm-dim2/dim2_hdm.c
 delete mode 100644 drivers/staging/most/hdm-dim2/dim2_hdm.h
 delete mode 100644 drivers/staging/most/hdm-dim2/dim2_reg.h
 delete mode 100644 drivers/staging/most/hdm-dim2/dim2_sysfs.c
 delete mode 100644 drivers/staging/most/hdm-dim2/dim2_sysfs.h
 delete mode 100644 drivers/staging/most/hdm-i2c/Kconfig
 delete mode 100644 drivers/staging/most/hdm-i2c/Makefile
 delete mode 100644 drivers/staging/most/hdm-i2c/hdm_i2c.c
 delete mode 100644 drivers/staging/most/hdm-usb/Kconfig
 delete mode 100644 drivers/staging/most/hdm-usb/Makefile
 delete mode 100644 drivers/staging/most/hdm-usb/hdm_usb.c
 create mode 100644 drivers/staging/most/i2c/Kconfig
 create mode 100644 drivers/staging/most/i2c/Makefile
 create mode 100644 drivers/staging/most/i2c/i2c.c
 delete mode 100644 drivers/staging/most/mostcore/Kconfig
 delete mode 100644 drivers/staging/most/mostcore/Makefile
 delete mode 100644 drivers/staging/most/mostcore/core.c
 delete mode 100644 drivers/staging/most/mostcore/mostcore.h
 create mode 100644 drivers/staging/most/net/Kconfig
 create mode 100644 drivers/staging/most/net/Makefile
 create mode 100644 drivers/staging/most/net/net.c
 create mode 100644 drivers/staging/most/sound/Kconfig
 create mode 100644 drivers/staging/most/sound/Makefile
 create mode 100644 drivers/staging/most/sound/sound.c
 create mode 100644 drivers/staging/most/usb/Kconfig
 create mode 100644 drivers/staging/most/usb/Makefile
 create mode 100644 drivers/staging/most/usb/usb.c
 create mode 100644 drivers/staging/most/video/Kconfig
 create mode 100644 drivers/staging/most/video/Makefile
 create mode 100644 drivers/staging/most/video/video.c

diff --git a/drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt b/drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt
new file mode 100644
index 0000000..543884d
--- /dev/null
+++ b/drivers/staging/most/Documentation/ABI/sysfs-bus-most.txt
@@ -0,0 +1,313 @@
+What:		/sys/bus/most/devices/.../description
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Provides information about the interface type and the physical
+		location of the device. Hardware attached via USB, for instance,
+		might return <usb_device 1-1.1:1.0>
+Users:
+
+What:		/sys/bus/most/devices/.../interface
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Indicates the type of peripheral interface the device uses.
+Users:
+
+What:		/sys/bus/most/devices/.../dci
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		If the network interface controller is attached via USB, a dci
+		directory is created that allows applications to read and
+		write the controller's DCI registers.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/arb_address
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to set an arbitrary DCI register address an
+		application wants to read from or write to.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/arb_value
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to read and write the DCI register whose address
+		is stored in arb_address.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/mep_eui48_hi
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to check and configure the MAC address.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/mep_eui48_lo
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to check and configure the MAC address.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/mep_eui48_mi
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to check and configure the MAC address.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/mep_filter
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to check and configure the MEP filter address.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/mep_hash0
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to check and configure the MEP hash table.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/mep_hash1
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to check and configure the MEP hash table.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/mep_hash2
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to check and configure the MEP hash table.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/mep_hash3
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to check and configure the MEP hash table.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/ni_state
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Indicates the current network interface state.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/node_address
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Indicates the current node address.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/node_position
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Indicates the current node position.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/packet_bandwidth
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Indicates the configured packet bandwidth.
+Users:
+
+What:		/sys/bus/most/devices/.../dci/sync_ep
+Date:		June 2016
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Triggers the controller's synchronization process for a certain
+		endpoint.
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		For every channel of the device a directory is created, whose
+		name is dictated by the HDM. This enables an application to
+		collect information about the channel's capabilities and
+		configure it.
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/available_datatypes
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Indicates the data types the current channel can transport.
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/available_directions
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Indicates the directions the current channel is capable of.
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/number_of_packet_buffers
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Indicates the number of packet buffers the current channel can
+		handle.
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/number_of_stream_buffers
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Indicates the number of streaming buffers the current channel can
+		handle.
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/size_of_packet_buffer
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Indicates the size of a packet buffer the current channel can
+		handle.
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/size_of_stream_buffer
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Indicates the size of a streaming buffer the current channel can
+		handle.
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/set_number_of_buffers
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is to configure the number of buffers of the current channel.
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/set_buffer_size
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is to configure the size of a buffer of the current channel.
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/set_direction
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is to configure the direction of the current channel.
+		The following strings will be accepted:
+			'dir_tx',
+			'dir_rx'
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/set_datatype
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is to configure the data type of the current channel.
+		The following strings will be accepted:
+			'control',
+			'async',
+			'sync',
+			'isoc_avp'
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/set_subbuffer_size
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is to configure the subbuffer size of the current channel.
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/set_packets_per_xact
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is to configure the number of packets per transaction of
+		the current channel. This is only needed network interface
+		controller is attached via USB.
+Users:
+
+What:		/sys/bus/most/devices/.../<channel>/channel_starving
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		Indicates whether current channel ran out of buffers.
+Users:
+
+What:		/sys/bus/most/drivers/mostcore/add_link
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to link a channel to a component of the
+		mostcore. A link created by writing to this file is
+		refered to as pipe.
+Users:
+
+What:		/sys/bus/most/drivers/mostcore/remove_link
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to unlink a channel from a component.
+Users:
+
+What:		/sys/bus/most/drivers/mostcore/components
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to retrieve a list of registered components.
+Users:
+
+What:		/sys/bus/most/drivers/mostcore/links
+Date:		March 2017
+KernelVersion:	4.15
+Contact:	Christian Gromm <christian.gromm@microchip.com>
+Description:
+		This is used to retrieve a list of established links.
+Users:
diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig
index 0b9b9b5..20047ab 100644
--- a/drivers/staging/most/Kconfig
+++ b/drivers/staging/most/Kconfig
@@ -1,10 +1,15 @@
 menuconfig MOST
-        tristate "MOST driver"
+        tristate "MOST support"
 	depends on HAS_DMA
-        select MOSTCORE
         default n
         ---help---
-          This option allows you to enable support for MOST Network transceivers.
+	  Say Y here if you want to enable MOST support.
+	  This driver needs at least one additional component to enable the
+	  desired access from userspace (e.g. character devices) and one that
+	  matches the network controller's hardware interface (e.g. USB).
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called most_core.
 
           If in doubt, say N here.
 
@@ -12,20 +17,18 @@ menuconfig MOST
 
 if MOST
 
-source "drivers/staging/most/mostcore/Kconfig"
-
-source "drivers/staging/most/aim-cdev/Kconfig"
+source "drivers/staging/most/cdev/Kconfig"
 
-source "drivers/staging/most/aim-network/Kconfig"
+source "drivers/staging/most/net/Kconfig"
 
-source "drivers/staging/most/aim-sound/Kconfig"
+source "drivers/staging/most/sound/Kconfig"
 
-source "drivers/staging/most/aim-v4l2/Kconfig"
+source "drivers/staging/most/video/Kconfig"
 
-source "drivers/staging/most/hdm-dim2/Kconfig"
+source "drivers/staging/most/dim2/Kconfig"
 
-source "drivers/staging/most/hdm-i2c/Kconfig"
+source "drivers/staging/most/i2c/Kconfig"
 
-source "drivers/staging/most/hdm-usb/Kconfig"
+source "drivers/staging/most/usb/Kconfig"
 
 endif
diff --git a/drivers/staging/most/Makefile b/drivers/staging/most/Makefile
index 9ee981c..2995309 100644
--- a/drivers/staging/most/Makefile
+++ b/drivers/staging/most/Makefile
@@ -1,8 +1,11 @@
-obj-$(CONFIG_MOSTCORE)	+= mostcore/
-obj-$(CONFIG_AIM_CDEV)	+= aim-cdev/
-obj-$(CONFIG_AIM_NETWORK)	+= aim-network/
-obj-$(CONFIG_AIM_SOUND)	+= aim-sound/
-obj-$(CONFIG_AIM_V4L2)	+= aim-v4l2/
-obj-$(CONFIG_HDM_DIM2)	+= hdm-dim2/
-obj-$(CONFIG_HDM_I2C)	+= hdm-i2c/
-obj-$(CONFIG_HDM_USB)	+= hdm-usb/
+obj-$(CONFIG_MOST) += most_core.o
+most_core-y := core.o
+ccflags-y += -Idrivers/staging/
+
+obj-$(CONFIG_MOST_CDEV)	+= cdev/
+obj-$(CONFIG_MOST_NET)	+= net/
+obj-$(CONFIG_MOST_SOUND)	+= sound/
+obj-$(CONFIG_MOST_VIDEO)	+= video/
+obj-$(CONFIG_MOST_DIM2)	+= dim2/
+obj-$(CONFIG_MOST_I2C)	+= i2c/
+obj-$(CONFIG_MOST_USB)	+= usb/
diff --git a/drivers/staging/most/aim-cdev/Kconfig b/drivers/staging/most/aim-cdev/Kconfig
deleted file mode 100644
index 3c59f1b..0000000
--- a/drivers/staging/most/aim-cdev/Kconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# MOST Cdev configuration
-#
-
-config AIM_CDEV
-	tristate "Cdev AIM"
-
-	---help---
-	  Say Y here if you want to commumicate via character devices.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called aim_cdev.
\ No newline at end of file
diff --git a/drivers/staging/most/aim-cdev/Makefile b/drivers/staging/most/aim-cdev/Makefile
deleted file mode 100644
index 0bcc6c6..0000000
--- a/drivers/staging/most/aim-cdev/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-obj-$(CONFIG_AIM_CDEV) += aim_cdev.o
-
-aim_cdev-objs := cdev.o
-ccflags-y += -Idrivers/staging/most/mostcore/
\ No newline at end of file
diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c
deleted file mode 100644
index 1e5cbc8..0000000
--- a/drivers/staging/most/aim-cdev/cdev.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * cdev.c - Application interfacing module for character devices
- *
- * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/cdev.h>
-#include <linux/poll.h>
-#include <linux/kfifo.h>
-#include <linux/uaccess.h>
-#include <linux/idr.h>
-#include "mostcore.h"
-
-static dev_t aim_devno;
-static struct class *aim_class;
-static struct ida minor_id;
-static unsigned int major;
-static struct most_aim cdev_aim;
-
-struct aim_channel {
-	wait_queue_head_t wq;
-	spinlock_t unlink;	/* synchronization lock to unlink channels */
-	struct cdev cdev;
-	struct device *dev;
-	struct mutex io_mutex;
-	struct most_interface *iface;
-	struct most_channel_config *cfg;
-	unsigned int channel_id;
-	dev_t devno;
-	size_t mbo_offs;
-	DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *));
-	int access_ref;
-	struct list_head list;
-};
-
-#define to_channel(d) container_of(d, struct aim_channel, cdev)
-static struct list_head channel_list;
-static spinlock_t ch_list_lock;
-
-static inline bool ch_has_mbo(struct aim_channel *c)
-{
-	return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0;
-}
-
-static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo)
-{
-	if (!kfifo_peek(&c->fifo, mbo)) {
-		*mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim);
-		if (*mbo)
-			kfifo_in(&c->fifo, mbo, 1);
-	}
-	return *mbo;
-}
-
-static struct aim_channel *get_channel(struct most_interface *iface, int id)
-{
-	struct aim_channel *c, *tmp;
-	unsigned long flags;
-	int found_channel = 0;
-
-	spin_lock_irqsave(&ch_list_lock, flags);
-	list_for_each_entry_safe(c, tmp, &channel_list, list) {
-		if ((c->iface == iface) && (c->channel_id == id)) {
-			found_channel = 1;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&ch_list_lock, flags);
-	if (!found_channel)
-		return NULL;
-	return c;
-}
-
-static void stop_channel(struct aim_channel *c)
-{
-	struct mbo *mbo;
-
-	while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1))
-		most_put_mbo(mbo);
-	most_stop_channel(c->iface, c->channel_id, &cdev_aim);
-}
-
-static void destroy_cdev(struct aim_channel *c)
-{
-	unsigned long flags;
-
-	device_destroy(aim_class, c->devno);
-	cdev_del(&c->cdev);
-	spin_lock_irqsave(&ch_list_lock, flags);
-	list_del(&c->list);
-	spin_unlock_irqrestore(&ch_list_lock, flags);
-}
-
-static void destroy_channel(struct aim_channel *c)
-{
-	ida_simple_remove(&minor_id, MINOR(c->devno));
-	kfifo_free(&c->fifo);
-	kfree(c);
-}
-
-/**
- * aim_open - implements the syscall to open the device
- * @inode: inode pointer
- * @filp: file pointer
- *
- * This stores the channel pointer in the private data field of
- * the file structure and activates the channel within the core.
- */
-static int aim_open(struct inode *inode, struct file *filp)
-{
-	struct aim_channel *c;
-	int ret;
-
-	c = to_channel(inode->i_cdev);
-	filp->private_data = c;
-
-	if (((c->cfg->direction == MOST_CH_RX) &&
-	     ((filp->f_flags & O_ACCMODE) != O_RDONLY)) ||
-	     ((c->cfg->direction == MOST_CH_TX) &&
-		((filp->f_flags & O_ACCMODE) != O_WRONLY))) {
-		pr_info("WARN: Access flags mismatch\n");
-		return -EACCES;
-	}
-
-	mutex_lock(&c->io_mutex);
-	if (!c->dev) {
-		pr_info("WARN: Device is destroyed\n");
-		mutex_unlock(&c->io_mutex);
-		return -ENODEV;
-	}
-
-	if (c->access_ref) {
-		pr_info("WARN: Device is busy\n");
-		mutex_unlock(&c->io_mutex);
-		return -EBUSY;
-	}
-
-	c->mbo_offs = 0;
-	ret = most_start_channel(c->iface, c->channel_id, &cdev_aim);
-	if (!ret)
-		c->access_ref = 1;
-	mutex_unlock(&c->io_mutex);
-	return ret;
-}
-
-/**
- * aim_close - implements the syscall to close the device
- * @inode: inode pointer
- * @filp: file pointer
- *
- * This stops the channel within the core.
- */
-static int aim_close(struct inode *inode, struct file *filp)
-{
-	struct aim_channel *c = to_channel(inode->i_cdev);
-
-	mutex_lock(&c->io_mutex);
-	spin_lock(&c->unlink);
-	c->access_ref = 0;
-	spin_unlock(&c->unlink);
-	if (c->dev) {
-		stop_channel(c);
-		mutex_unlock(&c->io_mutex);
-	} else {
-		mutex_unlock(&c->io_mutex);
-		destroy_channel(c);
-	}
-	return 0;
-}
-
-/**
- * aim_write - implements the syscall to write to the device
- * @filp: file pointer
- * @buf: pointer to user buffer
- * @count: number of bytes to write
- * @offset: offset from where to start writing
- */
-static ssize_t aim_write(struct file *filp, const char __user *buf,
-			 size_t count, loff_t *offset)
-{
-	int ret;
-	size_t to_copy, left;
-	struct mbo *mbo = NULL;
-	struct aim_channel *c = filp->private_data;
-
-	mutex_lock(&c->io_mutex);
-	while (c->dev && !ch_get_mbo(c, &mbo)) {
-		mutex_unlock(&c->io_mutex);
-
-		if ((filp->f_flags & O_NONBLOCK))
-			return -EAGAIN;
-		if (wait_event_interruptible(c->wq, ch_has_mbo(c) || !c->dev))
-			return -ERESTARTSYS;
-		mutex_lock(&c->io_mutex);
-	}
-
-	if (unlikely(!c->dev)) {
-		ret = -ENODEV;
-		goto unlock;
-	}
-
-	to_copy = min(count, c->cfg->buffer_size - c->mbo_offs);
-	left = copy_from_user(mbo->virt_address + c->mbo_offs, buf, to_copy);
-	if (left == to_copy) {
-		ret = -EFAULT;
-		goto unlock;
-	}
-
-	c->mbo_offs += to_copy - left;
-	if (c->mbo_offs >= c->cfg->buffer_size ||
-	    c->cfg->data_type == MOST_CH_CONTROL ||
-	    c->cfg->data_type == MOST_CH_ASYNC) {
-		kfifo_skip(&c->fifo);
-		mbo->buffer_length = c->mbo_offs;
-		c->mbo_offs = 0;
-		most_submit_mbo(mbo);
-	}
-
-	ret = to_copy - left;
-unlock:
-	mutex_unlock(&c->io_mutex);
-	return ret;
-}
-
-/**
- * aim_read - implements the syscall to read from the device
- * @filp: file pointer
- * @buf: pointer to user buffer
- * @count: number of bytes to read
- * @offset: offset from where to start reading
- */
-static ssize_t
-aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
-{
-	size_t to_copy, not_copied, copied;
-	struct mbo *mbo;
-	struct aim_channel *c = filp->private_data;
-
-	mutex_lock(&c->io_mutex);
-	while (c->dev && !kfifo_peek(&c->fifo, &mbo)) {
-		mutex_unlock(&c->io_mutex);
-		if (filp->f_flags & O_NONBLOCK)
-			return -EAGAIN;
-		if (wait_event_interruptible(c->wq,
-					     (!kfifo_is_empty(&c->fifo) ||
-					      (!c->dev))))
-			return -ERESTARTSYS;
-		mutex_lock(&c->io_mutex);
-	}
-
-	/* make sure we don't submit to gone devices */
-	if (unlikely(!c->dev)) {
-		mutex_unlock(&c->io_mutex);
-		return -ENODEV;
-	}
-
-	to_copy = min_t(size_t,
-			count,
-			mbo->processed_length - c->mbo_offs);
-
-	not_copied = copy_to_user(buf,
-				  mbo->virt_address + c->mbo_offs,
-				  to_copy);
-
-	copied = to_copy - not_copied;
-
-	c->mbo_offs += copied;
-	if (c->mbo_offs >= mbo->processed_length) {
-		kfifo_skip(&c->fifo);
-		most_put_mbo(mbo);
-		c->mbo_offs = 0;
-	}
-	mutex_unlock(&c->io_mutex);
-	return copied;
-}
-
-static unsigned int aim_poll(struct file *filp, poll_table *wait)
-{
-	struct aim_channel *c = filp->private_data;
-	unsigned int mask = 0;
-
-	poll_wait(filp, &c->wq, wait);
-
-	if (c->cfg->direction == MOST_CH_RX) {
-		if (!kfifo_is_empty(&c->fifo))
-			mask |= POLLIN | POLLRDNORM;
-	} else {
-		if (!kfifo_is_empty(&c->fifo) || ch_has_mbo(c))
-			mask |= POLLOUT | POLLWRNORM;
-	}
-	return mask;
-}
-
-/**
- * Initialization of struct file_operations
- */
-static const struct file_operations channel_fops = {
-	.owner = THIS_MODULE,
-	.read = aim_read,
-	.write = aim_write,
-	.open = aim_open,
-	.release = aim_close,
-	.poll = aim_poll,
-};
-
-/**
- * aim_disconnect_channel - disconnect a channel
- * @iface: pointer to interface instance
- * @channel_id: channel index
- *
- * This frees allocated memory and removes the cdev that represents this
- * channel in user space.
- */
-static int aim_disconnect_channel(struct most_interface *iface, int channel_id)
-{
-	struct aim_channel *c;
-
-	if (!iface) {
-		pr_info("Bad interface pointer\n");
-		return -EINVAL;
-	}
-
-	c = get_channel(iface, channel_id);
-	if (!c)
-		return -ENXIO;
-
-	mutex_lock(&c->io_mutex);
-	spin_lock(&c->unlink);
-	c->dev = NULL;
-	spin_unlock(&c->unlink);
-	destroy_cdev(c);
-	if (c->access_ref) {
-		stop_channel(c);
-		wake_up_interruptible(&c->wq);
-		mutex_unlock(&c->io_mutex);
-	} else {
-		mutex_unlock(&c->io_mutex);
-		destroy_channel(c);
-	}
-	return 0;
-}
-
-/**
- * aim_rx_completion - completion handler for rx channels
- * @mbo: pointer to buffer object that has completed
- *
- * This searches for the channel linked to this MBO and stores it in the local
- * fifo buffer.
- */
-static int aim_rx_completion(struct mbo *mbo)
-{
-	struct aim_channel *c;
-
-	if (!mbo)
-		return -EINVAL;
-
-	c = get_channel(mbo->ifp, mbo->hdm_channel_id);
-	if (!c)
-		return -ENXIO;
-
-	spin_lock(&c->unlink);
-	if (!c->access_ref || !c->dev) {
-		spin_unlock(&c->unlink);
-		return -ENODEV;
-	}
-	kfifo_in(&c->fifo, &mbo, 1);
-	spin_unlock(&c->unlink);
-#ifdef DEBUG_MESG
-	if (kfifo_is_full(&c->fifo))
-		pr_info("WARN: Fifo is full\n");
-#endif
-	wake_up_interruptible(&c->wq);
-	return 0;
-}
-
-/**
- * aim_tx_completion - completion handler for tx channels
- * @iface: pointer to interface instance
- * @channel_id: channel index/ID
- *
- * This wakes sleeping processes in the wait-queue.
- */
-static int aim_tx_completion(struct most_interface *iface, int channel_id)
-{
-	struct aim_channel *c;
-
-	if (!iface) {
-		pr_info("Bad interface pointer\n");
-		return -EINVAL;
-	}
-	if ((channel_id < 0) || (channel_id >= iface->num_channels)) {
-		pr_info("Channel ID out of range\n");
-		return -EINVAL;
-	}
-
-	c = get_channel(iface, channel_id);
-	if (!c)
-		return -ENXIO;
-	wake_up_interruptible(&c->wq);
-	return 0;
-}
-
-/**
- * aim_probe - probe function of the driver module
- * @iface: pointer to interface instance
- * @channel_id: channel index/ID
- * @cfg: pointer to actual channel configuration
- * @parent: pointer to kobject (needed for sysfs hook-up)
- * @name: name of the device to be created
- *
- * This allocates achannel object and creates the device node in /dev
- *
- * Returns 0 on success or error code otherwise.
- */
-static int aim_probe(struct most_interface *iface, int channel_id,
-		     struct most_channel_config *cfg,
-		     struct kobject *parent, char *name)
-{
-	struct aim_channel *c;
-	unsigned long cl_flags;
-	int retval;
-	int current_minor;
-
-	if ((!iface) || (!cfg) || (!parent) || (!name)) {
-		pr_info("Probing AIM with bad arguments");
-		return -EINVAL;
-	}
-	c = get_channel(iface, channel_id);
-	if (c)
-		return -EEXIST;
-
-	current_minor = ida_simple_get(&minor_id, 0, 0, GFP_KERNEL);
-	if (current_minor < 0)
-		return current_minor;
-
-	c = kzalloc(sizeof(*c), GFP_KERNEL);
-	if (!c) {
-		retval = -ENOMEM;
-		goto error_alloc_channel;
-	}
-
-	c->devno = MKDEV(major, current_minor);
-	cdev_init(&c->cdev, &channel_fops);
-	c->cdev.owner = THIS_MODULE;
-	cdev_add(&c->cdev, c->devno, 1);
-	c->iface = iface;
-	c->cfg = cfg;
-	c->channel_id = channel_id;
-	c->access_ref = 0;
-	spin_lock_init(&c->unlink);
-	INIT_KFIFO(c->fifo);
-	retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL);
-	if (retval) {
-		pr_info("failed to alloc channel kfifo");
-		goto error_alloc_kfifo;
-	}
-	init_waitqueue_head(&c->wq);
-	mutex_init(&c->io_mutex);
-	spin_lock_irqsave(&ch_list_lock, cl_flags);
-	list_add_tail(&c->list, &channel_list);
-	spin_unlock_irqrestore(&ch_list_lock, cl_flags);
-	c->dev = device_create(aim_class,
-				     NULL,
-				     c->devno,
-				     NULL,
-				     "%s", name);
-
-	if (IS_ERR(c->dev)) {
-		retval = PTR_ERR(c->dev);
-		pr_info("failed to create new device node %s\n", name);
-		goto error_create_device;
-	}
-	kobject_uevent(&c->dev->kobj, KOBJ_ADD);
-	return 0;
-
-error_create_device:
-	kfifo_free(&c->fifo);
-	list_del(&c->list);
-error_alloc_kfifo:
-	cdev_del(&c->cdev);
-	kfree(c);
-error_alloc_channel:
-	ida_simple_remove(&minor_id, current_minor);
-	return retval;
-}
-
-static struct most_aim cdev_aim = {
-	.name = "cdev",
-	.probe_channel = aim_probe,
-	.disconnect_channel = aim_disconnect_channel,
-	.rx_completion = aim_rx_completion,
-	.tx_completion = aim_tx_completion,
-};
-
-static int __init mod_init(void)
-{
-	int err;
-
-	pr_info("init()\n");
-
-	INIT_LIST_HEAD(&channel_list);
-	spin_lock_init(&ch_list_lock);
-	ida_init(&minor_id);
-
-	err = alloc_chrdev_region(&aim_devno, 0, 50, "cdev");
-	if (err < 0)
-		goto dest_ida;
-	major = MAJOR(aim_devno);
-
-	aim_class = class_create(THIS_MODULE, "most_cdev_aim");
-	if (IS_ERR(aim_class)) {
-		pr_err("no udev support\n");
-		err = PTR_ERR(aim_class);
-		goto free_cdev;
-	}
-	err = most_register_aim(&cdev_aim);
-	if (err)
-		goto dest_class;
-	return 0;
-
-dest_class:
-	class_destroy(aim_class);
-free_cdev:
-	unregister_chrdev_region(aim_devno, 1);
-dest_ida:
-	ida_destroy(&minor_id);
-	return err;
-}
-
-static void __exit mod_exit(void)
-{
-	struct aim_channel *c, *tmp;
-
-	pr_info("exit module\n");
-
-	most_deregister_aim(&cdev_aim);
-
-	list_for_each_entry_safe(c, tmp, &channel_list, list) {
-		destroy_cdev(c);
-		destroy_channel(c);
-	}
-	class_destroy(aim_class);
-	unregister_chrdev_region(aim_devno, 1);
-	ida_destroy(&minor_id);
-}
-
-module_init(mod_init);
-module_exit(mod_exit);
-MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("character device AIM for mostcore");
diff --git a/drivers/staging/most/aim-network/Kconfig b/drivers/staging/most/aim-network/Kconfig
deleted file mode 100644
index 4c66b24..0000000
--- a/drivers/staging/most/aim-network/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# MOST Networking configuration
-#
-
-config AIM_NETWORK
-	tristate "Networking AIM"
-	depends on NET
-
-	---help---
-	  Say Y here if you want to commumicate via a networking device.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called aim_network.
diff --git a/drivers/staging/most/aim-network/Makefile b/drivers/staging/most/aim-network/Makefile
deleted file mode 100644
index 840c1dd..0000000
--- a/drivers/staging/most/aim-network/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-obj-$(CONFIG_AIM_NETWORK) += aim_network.o
-
-aim_network-objs := networking.o
-ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
deleted file mode 100644
index 936f013..0000000
--- a/drivers/staging/most/aim-network/networking.c
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
- * Networking AIM - Networking Application Interface Module for MostCore
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/wait.h>
-#include <linux/kobject.h>
-#include "mostcore.h"
-
-#define MEP_HDR_LEN 8
-#define MDP_HDR_LEN 16
-#define MAMAC_DATA_LEN (1024 - MDP_HDR_LEN)
-
-#define PMHL 5
-
-#define PMS_TELID_UNSEGM_MAMAC	0x0A
-#define PMS_FIFONO_MDP		0x01
-#define PMS_FIFONO_MEP		0x04
-#define PMS_MSGTYPE_DATA	0x04
-#define PMS_DEF_PRIO		0
-#define MEP_DEF_RETRY		15
-
-#define PMS_FIFONO_MASK		0x07
-#define PMS_FIFONO_SHIFT	3
-#define PMS_RETRY_SHIFT		4
-#define PMS_TELID_MASK		0x0F
-#define PMS_TELID_SHIFT		4
-
-#define HB(value)		((u8)((u16)(value) >> 8))
-#define LB(value)		((u8)(value))
-
-#define EXTRACT_BIT_SET(bitset_name, value) \
-	(((value) >> bitset_name##_SHIFT) & bitset_name##_MASK)
-
-#define PMS_IS_MEP(buf, len) \
-	((len) > MEP_HDR_LEN && \
-	 EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MEP)
-
-#define PMS_IS_MAMAC(buf, len) \
-	((len) > MDP_HDR_LEN && \
-	 EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MDP && \
-	 EXTRACT_BIT_SET(PMS_TELID, (buf)[14]) == PMS_TELID_UNSEGM_MAMAC)
-
-struct net_dev_channel {
-	bool linked;
-	int ch_id;
-};
-
-struct net_dev_context {
-	struct most_interface *iface;
-	bool is_mamac;
-	struct net_device *dev;
-	struct net_dev_channel rx;
-	struct net_dev_channel tx;
-	struct list_head list;
-};
-
-static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
-static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */
-static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */
-static struct most_aim aim;
-
-static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
-{
-	u8 *buff = mbo->virt_address;
-	const u8 broadcast[] = { 0x03, 0xFF };
-	const u8 *dest_addr = skb->data + 4;
-	const u8 *eth_type = skb->data + 12;
-	unsigned int payload_len = skb->len - ETH_HLEN;
-	unsigned int mdp_len = payload_len + MDP_HDR_LEN;
-
-	if (mbo->buffer_length < mdp_len) {
-		pr_err("drop: too small buffer! (%d for %d)\n",
-		       mbo->buffer_length, mdp_len);
-		return -EINVAL;
-	}
-
-	if (skb->len < ETH_HLEN) {
-		pr_err("drop: too small packet! (%d)\n", skb->len);
-		return -EINVAL;
-	}
-
-	if (dest_addr[0] == 0xFF && dest_addr[1] == 0xFF)
-		dest_addr = broadcast;
-
-	*buff++ = HB(mdp_len - 2);
-	*buff++ = LB(mdp_len - 2);
-
-	*buff++ = PMHL;
-	*buff++ = (PMS_FIFONO_MDP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
-	*buff++ = PMS_DEF_PRIO;
-	*buff++ = dest_addr[0];
-	*buff++ = dest_addr[1];
-	*buff++ = 0x00;
-
-	*buff++ = HB(payload_len + 6);
-	*buff++ = LB(payload_len + 6);
-
-	/* end of FPH here */
-
-	*buff++ = eth_type[0];
-	*buff++ = eth_type[1];
-	*buff++ = 0;
-	*buff++ = 0;
-
-	*buff++ = PMS_TELID_UNSEGM_MAMAC << 4 | HB(payload_len);
-	*buff++ = LB(payload_len);
-
-	memcpy(buff, skb->data + ETH_HLEN, payload_len);
-	mbo->buffer_length = mdp_len;
-	return 0;
-}
-
-static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo)
-{
-	u8 *buff = mbo->virt_address;
-	unsigned int mep_len = skb->len + MEP_HDR_LEN;
-
-	if (mbo->buffer_length < mep_len) {
-		pr_err("drop: too small buffer! (%d for %d)\n",
-		       mbo->buffer_length, mep_len);
-		return -EINVAL;
-	}
-
-	*buff++ = HB(mep_len - 2);
-	*buff++ = LB(mep_len - 2);
-
-	*buff++ = PMHL;
-	*buff++ = (PMS_FIFONO_MEP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
-	*buff++ = (MEP_DEF_RETRY << PMS_RETRY_SHIFT) | PMS_DEF_PRIO;
-	*buff++ = 0;
-	*buff++ = 0;
-	*buff++ = 0;
-
-	memcpy(buff, skb->data, skb->len);
-	mbo->buffer_length = mep_len;
-	return 0;
-}
-
-static int most_nd_set_mac_address(struct net_device *dev, void *p)
-{
-	struct net_dev_context *nd = netdev_priv(dev);
-	int err = eth_mac_addr(dev, p);
-
-	if (err)
-		return err;
-
-	nd->is_mamac =
-		(dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 &&
-		 dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0);
-
-	/*
-	 * Set default MTU for the given packet type.
-	 * It is still possible to change MTU using ip tools afterwards.
-	 */
-	dev->mtu = nd->is_mamac ? MAMAC_DATA_LEN : ETH_DATA_LEN;
-
-	return 0;
-}
-
-static void on_netinfo(struct most_interface *iface,
-		       unsigned char link_stat, unsigned char *mac_addr);
-
-static int most_nd_open(struct net_device *dev)
-{
-	struct net_dev_context *nd = netdev_priv(dev);
-	int ret = 0;
-
-	mutex_lock(&probe_disc_mt);
-
-	if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) {
-		netdev_err(dev, "most_start_channel() failed\n");
-		ret = -EBUSY;
-		goto unlock;
-	}
-
-	if (most_start_channel(nd->iface, nd->tx.ch_id, &aim)) {
-		netdev_err(dev, "most_start_channel() failed\n");
-		most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
-		ret = -EBUSY;
-		goto unlock;
-	}
-
-	netif_carrier_off(dev);
-	if (is_valid_ether_addr(dev->dev_addr))
-		netif_dormant_off(dev);
-	else
-		netif_dormant_on(dev);
-	netif_wake_queue(dev);
-	if (nd->iface->request_netinfo)
-		nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, on_netinfo);
-
-unlock:
-	mutex_unlock(&probe_disc_mt);
-	return ret;
-}
-
-static int most_nd_stop(struct net_device *dev)
-{
-	struct net_dev_context *nd = netdev_priv(dev);
-
-	netif_stop_queue(dev);
-	if (nd->iface->request_netinfo)
-		nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, NULL);
-	most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
-	most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
-
-	return 0;
-}
-
-static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb,
-				      struct net_device *dev)
-{
-	struct net_dev_context *nd = netdev_priv(dev);
-	struct mbo *mbo;
-	int ret;
-
-	mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim);
-
-	if (!mbo) {
-		netif_stop_queue(dev);
-		dev->stats.tx_fifo_errors++;
-		return NETDEV_TX_BUSY;
-	}
-
-	if (nd->is_mamac)
-		ret = skb_to_mamac(skb, mbo);
-	else
-		ret = skb_to_mep(skb, mbo);
-
-	if (ret) {
-		most_put_mbo(mbo);
-		dev->stats.tx_dropped++;
-		kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	most_submit_mbo(mbo);
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
-	kfree_skb(skb);
-	return NETDEV_TX_OK;
-}
-
-static const struct net_device_ops most_nd_ops = {
-	.ndo_open = most_nd_open,
-	.ndo_stop = most_nd_stop,
-	.ndo_start_xmit = most_nd_start_xmit,
-	.ndo_set_mac_address = most_nd_set_mac_address,
-};
-
-static void most_nd_setup(struct net_device *dev)
-{
-	ether_setup(dev);
-	dev->netdev_ops = &most_nd_ops;
-}
-
-static struct net_dev_context *get_net_dev(struct most_interface *iface)
-{
-	struct net_dev_context *nd;
-
-	list_for_each_entry(nd, &net_devices, list)
-		if (nd->iface == iface)
-			return nd;
-	return NULL;
-}
-
-static struct net_dev_context *get_net_dev_hold(struct most_interface *iface)
-{
-	struct net_dev_context *nd;
-	unsigned long flags;
-
-	spin_lock_irqsave(&list_lock, flags);
-	nd = get_net_dev(iface);
-	if (nd && nd->rx.linked && nd->tx.linked)
-		dev_hold(nd->dev);
-	else
-		nd = NULL;
-	spin_unlock_irqrestore(&list_lock, flags);
-	return nd;
-}
-
-static int aim_probe_channel(struct most_interface *iface, int channel_idx,
-			     struct most_channel_config *ccfg,
-			     struct kobject *parent, char *name)
-{
-	struct net_dev_context *nd;
-	struct net_dev_channel *ch;
-	struct net_device *dev;
-	unsigned long flags;
-	int ret = 0;
-
-	if (!iface)
-		return -EINVAL;
-
-	if (ccfg->data_type != MOST_CH_ASYNC)
-		return -EINVAL;
-
-	mutex_lock(&probe_disc_mt);
-	nd = get_net_dev(iface);
-	if (!nd) {
-		dev = alloc_netdev(sizeof(struct net_dev_context), "meth%d",
-				   NET_NAME_UNKNOWN, most_nd_setup);
-		if (!dev) {
-			ret = -ENOMEM;
-			goto unlock;
-		}
-
-		nd = netdev_priv(dev);
-		nd->iface = iface;
-		nd->dev = dev;
-
-		spin_lock_irqsave(&list_lock, flags);
-		list_add(&nd->list, &net_devices);
-		spin_unlock_irqrestore(&list_lock, flags);
-
-		ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
-	} else {
-		ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
-		if (ch->linked) {
-			pr_err("direction is allocated\n");
-			ret = -EINVAL;
-			goto unlock;
-		}
-
-		if (register_netdev(nd->dev)) {
-			pr_err("register_netdev() failed\n");
-			ret = -EINVAL;
-			goto unlock;
-		}
-	}
-	ch->ch_id = channel_idx;
-	ch->linked = true;
-
-unlock:
-	mutex_unlock(&probe_disc_mt);
-	return ret;
-}
-
-static int aim_disconnect_channel(struct most_interface *iface,
-				  int channel_idx)
-{
-	struct net_dev_context *nd;
-	struct net_dev_channel *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	mutex_lock(&probe_disc_mt);
-	nd = get_net_dev(iface);
-	if (!nd) {
-		ret = -EINVAL;
-		goto unlock;
-	}
-
-	if (nd->rx.linked && channel_idx == nd->rx.ch_id) {
-		ch = &nd->rx;
-	} else if (nd->tx.linked && channel_idx == nd->tx.ch_id) {
-		ch = &nd->tx;
-	} else {
-		ret = -EINVAL;
-		goto unlock;
-	}
-
-	if (nd->rx.linked && nd->tx.linked) {
-		spin_lock_irqsave(&list_lock, flags);
-		ch->linked = false;
-		spin_unlock_irqrestore(&list_lock, flags);
-
-		/*
-		 * do not call most_stop_channel() here, because channels are
-		 * going to be closed in ndo_stop() after unregister_netdev()
-		 */
-		unregister_netdev(nd->dev);
-	} else {
-		spin_lock_irqsave(&list_lock, flags);
-		list_del(&nd->list);
-		spin_unlock_irqrestore(&list_lock, flags);
-
-		free_netdev(nd->dev);
-	}
-
-unlock:
-	mutex_unlock(&probe_disc_mt);
-	return ret;
-}
-
-static int aim_resume_tx_channel(struct most_interface *iface,
-				 int channel_idx)
-{
-	struct net_dev_context *nd;
-
-	nd = get_net_dev_hold(iface);
-	if (!nd)
-		return 0;
-
-	if (nd->tx.ch_id != channel_idx)
-		goto put_nd;
-
-	netif_wake_queue(nd->dev);
-
-put_nd:
-	dev_put(nd->dev);
-	return 0;
-}
-
-static int aim_rx_data(struct mbo *mbo)
-{
-	const u32 zero = 0;
-	struct net_dev_context *nd;
-	char *buf = mbo->virt_address;
-	u32 len = mbo->processed_length;
-	struct sk_buff *skb;
-	struct net_device *dev;
-	unsigned int skb_len;
-	int ret = 0;
-
-	nd = get_net_dev_hold(mbo->ifp);
-	if (!nd)
-		return -EIO;
-
-	if (nd->rx.ch_id != mbo->hdm_channel_id) {
-		ret = -EIO;
-		goto put_nd;
-	}
-
-	dev = nd->dev;
-
-	if (nd->is_mamac) {
-		if (!PMS_IS_MAMAC(buf, len)) {
-			ret = -EIO;
-			goto put_nd;
-		}
-
-		skb = dev_alloc_skb(len - MDP_HDR_LEN + 2 * ETH_ALEN + 2);
-	} else {
-		if (!PMS_IS_MEP(buf, len)) {
-			ret = -EIO;
-			goto put_nd;
-		}
-
-		skb = dev_alloc_skb(len - MEP_HDR_LEN);
-	}
-
-	if (!skb) {
-		dev->stats.rx_dropped++;
-		pr_err_once("drop packet: no memory for skb\n");
-		goto out;
-	}
-
-	skb->dev = dev;
-
-	if (nd->is_mamac) {
-		/* dest */
-		ether_addr_copy(skb_put(skb, ETH_ALEN), dev->dev_addr);
-
-		/* src */
-		skb_put_data(skb, &zero, 4);
-		skb_put_data(skb, buf + 5, 2);
-
-		/* eth type */
-		skb_put_data(skb, buf + 10, 2);
-
-		buf += MDP_HDR_LEN;
-		len -= MDP_HDR_LEN;
-	} else {
-		buf += MEP_HDR_LEN;
-		len -= MEP_HDR_LEN;
-	}
-
-	skb_put_data(skb, buf, len);
-	skb->protocol = eth_type_trans(skb, dev);
-	skb_len = skb->len;
-	if (netif_rx(skb) == NET_RX_SUCCESS) {
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += skb_len;
-	} else {
-		dev->stats.rx_dropped++;
-	}
-
-out:
-	most_put_mbo(mbo);
-
-put_nd:
-	dev_put(nd->dev);
-	return ret;
-}
-
-static struct most_aim aim = {
-	.name = "networking",
-	.probe_channel = aim_probe_channel,
-	.disconnect_channel = aim_disconnect_channel,
-	.tx_completion = aim_resume_tx_channel,
-	.rx_completion = aim_rx_data,
-};
-
-static int __init most_net_init(void)
-{
-	spin_lock_init(&list_lock);
-	mutex_init(&probe_disc_mt);
-	return most_register_aim(&aim);
-}
-
-static void __exit most_net_exit(void)
-{
-	most_deregister_aim(&aim);
-}
-
-/**
- * on_netinfo - callback for HDM to be informed about HW's MAC
- * @param iface - most interface instance
- * @param link_stat - link status
- * @param mac_addr - MAC address
- */
-static void on_netinfo(struct most_interface *iface,
-		       unsigned char link_stat, unsigned char *mac_addr)
-{
-	struct net_dev_context *nd;
-	struct net_device *dev;
-	const u8 *m = mac_addr;
-
-	nd = get_net_dev_hold(iface);
-	if (!nd)
-		return;
-
-	dev = nd->dev;
-
-	if (link_stat)
-		netif_carrier_on(dev);
-	else
-		netif_carrier_off(dev);
-
-	if (m && is_valid_ether_addr(m)) {
-		if (!is_valid_ether_addr(dev->dev_addr)) {
-			netdev_info(dev, "set mac %02x-%02x-%02x-%02x-%02x-%02x\n",
-				    m[0], m[1], m[2], m[3], m[4], m[5]);
-			ether_addr_copy(dev->dev_addr, m);
-			netif_dormant_off(dev);
-		} else if (!ether_addr_equal(dev->dev_addr, m)) {
-			netdev_warn(dev, "reject mac %02x-%02x-%02x-%02x-%02x-%02x\n",
-				    m[0], m[1], m[2], m[3], m[4], m[5]);
-		}
-	}
-
-	dev_put(nd->dev);
-}
-
-module_init(most_net_init);
-module_exit(most_net_exit);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
-MODULE_DESCRIPTION("Networking Application Interface Module for MostCore");
diff --git a/drivers/staging/most/aim-sound/Kconfig b/drivers/staging/most/aim-sound/Kconfig
deleted file mode 100644
index 3194c21..0000000
--- a/drivers/staging/most/aim-sound/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# MOST ALSA configuration
-#
-
-config AIM_SOUND
-	tristate "ALSA AIM"
-	depends on SND
-	select SND_PCM
-	---help---
-	  Say Y here if you want to commumicate via ALSA/sound devices.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called aim_sound.
diff --git a/drivers/staging/most/aim-sound/Makefile b/drivers/staging/most/aim-sound/Makefile
deleted file mode 100644
index beba958..0000000
--- a/drivers/staging/most/aim-sound/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-obj-$(CONFIG_AIM_SOUND) += aim_sound.o
-
-aim_sound-objs := sound.o
-ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c
deleted file mode 100644
index ea1366a..0000000
--- a/drivers/staging/most/aim-sound/sound.c
+++ /dev/null
@@ -1,765 +0,0 @@
-/*
- * sound.c - Audio Application Interface Module for Mostcore
- *
- * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/printk.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-#include <mostcore.h>
-
-#define DRIVER_NAME "sound"
-
-static struct list_head dev_list;
-static struct most_aim audio_aim;
-
-/**
- * struct channel - private structure to keep channel specific data
- * @substream: stores the substream structure
- * @iface: interface for which the channel belongs to
- * @cfg: channel configuration
- * @card: registered sound card
- * @list: list for private use
- * @id: channel index
- * @period_pos: current period position (ring buffer)
- * @buffer_pos: current buffer position (ring buffer)
- * @is_stream_running: identifies whether a stream is running or not
- * @opened: set when the stream is opened
- * @playback_task: playback thread
- * @playback_waitq: waitq used by playback thread
- */
-struct channel {
-	struct snd_pcm_substream *substream;
-	struct snd_pcm_hardware pcm_hardware;
-	struct most_interface *iface;
-	struct most_channel_config *cfg;
-	struct snd_card *card;
-	struct list_head list;
-	int id;
-	unsigned int period_pos;
-	unsigned int buffer_pos;
-	bool is_stream_running;
-
-	struct task_struct *playback_task;
-	wait_queue_head_t playback_waitq;
-
-	void (*copy_fn)(void *alsa, void *most, unsigned int bytes);
-};
-
-#define MOST_PCM_INFO (SNDRV_PCM_INFO_MMAP | \
-		       SNDRV_PCM_INFO_MMAP_VALID | \
-		       SNDRV_PCM_INFO_BATCH | \
-		       SNDRV_PCM_INFO_INTERLEAVED | \
-		       SNDRV_PCM_INFO_BLOCK_TRANSFER)
-
-#define swap16(val) ( \
-	(((u16)(val) << 8) & (u16)0xFF00) | \
-	(((u16)(val) >> 8) & (u16)0x00FF))
-
-#define swap32(val) ( \
-	(((u32)(val) << 24) & (u32)0xFF000000) | \
-	(((u32)(val) <<  8) & (u32)0x00FF0000) | \
-	(((u32)(val) >>  8) & (u32)0x0000FF00) | \
-	(((u32)(val) >> 24) & (u32)0x000000FF))
-
-static void swap_copy16(u16 *dest, const u16 *source, unsigned int bytes)
-{
-	unsigned int i = 0;
-
-	while (i < (bytes / 2)) {
-		dest[i] = swap16(source[i]);
-		i++;
-	}
-}
-
-static void swap_copy24(u8 *dest, const u8 *source, unsigned int bytes)
-{
-	unsigned int i = 0;
-
-	while (i < bytes - 2) {
-		dest[i] = source[i + 2];
-		dest[i + 1] = source[i + 1];
-		dest[i + 2] = source[i];
-		i += 3;
-	}
-}
-
-static void swap_copy32(u32 *dest, const u32 *source, unsigned int bytes)
-{
-	unsigned int i = 0;
-
-	while (i < bytes / 4) {
-		dest[i] = swap32(source[i]);
-		i++;
-	}
-}
-
-static void alsa_to_most_memcpy(void *alsa, void *most, unsigned int bytes)
-{
-	memcpy(most, alsa, bytes);
-}
-
-static void alsa_to_most_copy16(void *alsa, void *most, unsigned int bytes)
-{
-	swap_copy16(most, alsa, bytes);
-}
-
-static void alsa_to_most_copy24(void *alsa, void *most, unsigned int bytes)
-{
-	swap_copy24(most, alsa, bytes);
-}
-
-static void alsa_to_most_copy32(void *alsa, void *most, unsigned int bytes)
-{
-	swap_copy32(most, alsa, bytes);
-}
-
-static void most_to_alsa_memcpy(void *alsa, void *most, unsigned int bytes)
-{
-	memcpy(alsa, most, bytes);
-}
-
-static void most_to_alsa_copy16(void *alsa, void *most, unsigned int bytes)
-{
-	swap_copy16(alsa, most, bytes);
-}
-
-static void most_to_alsa_copy24(void *alsa, void *most, unsigned int bytes)
-{
-	swap_copy24(alsa, most, bytes);
-}
-
-static void most_to_alsa_copy32(void *alsa, void *most, unsigned int bytes)
-{
-	swap_copy32(alsa, most, bytes);
-}
-
-/**
- * get_channel - get pointer to channel
- * @iface: interface structure
- * @channel_id: channel ID
- *
- * This traverses the channel list and returns the channel matching the
- * ID and interface.
- *
- * Returns pointer to channel on success or NULL otherwise.
- */
-static struct channel *get_channel(struct most_interface *iface,
-				   int channel_id)
-{
-	struct channel *channel, *tmp;
-
-	list_for_each_entry_safe(channel, tmp, &dev_list, list) {
-		if ((channel->iface == iface) && (channel->id == channel_id))
-			return channel;
-	}
-
-	return NULL;
-}
-
-/**
- * copy_data - implements data copying function
- * @channel: channel
- * @mbo: MBO from core
- *
- * Copy data from/to ring buffer to/from MBO and update the buffer position
- */
-static bool copy_data(struct channel *channel, struct mbo *mbo)
-{
-	struct snd_pcm_runtime *const runtime = channel->substream->runtime;
-	unsigned int const frame_bytes = channel->cfg->subbuffer_size;
-	unsigned int const buffer_size = runtime->buffer_size;
-	unsigned int frames;
-	unsigned int fr0;
-
-	if (channel->cfg->direction & MOST_CH_RX)
-		frames = mbo->processed_length / frame_bytes;
-	else
-		frames = mbo->buffer_length / frame_bytes;
-	fr0 = min(buffer_size - channel->buffer_pos, frames);
-
-	channel->copy_fn(runtime->dma_area + channel->buffer_pos * frame_bytes,
-			 mbo->virt_address,
-			 fr0 * frame_bytes);
-
-	if (frames > fr0) {
-		/* wrap around at end of ring buffer */
-		channel->copy_fn(runtime->dma_area,
-				 mbo->virt_address + fr0 * frame_bytes,
-				 (frames - fr0) * frame_bytes);
-	}
-
-	channel->buffer_pos += frames;
-	if (channel->buffer_pos >= buffer_size)
-		channel->buffer_pos -= buffer_size;
-	channel->period_pos += frames;
-	if (channel->period_pos >= runtime->period_size) {
-		channel->period_pos -= runtime->period_size;
-		return true;
-	}
-
-	return false;
-}
-
-/**
- * playback_thread - function implements the playback thread
- * @data: private data
- *
- * Thread which does the playback functionality in a loop. It waits for a free
- * MBO from mostcore for a particular channel and copy the data from ring buffer
- * to MBO. Submit the MBO back to mostcore, after copying the data.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int playback_thread(void *data)
-{
-	struct channel *const channel = data;
-
-	while (!kthread_should_stop()) {
-		struct mbo *mbo = NULL;
-		bool period_elapsed = false;
-
-		wait_event_interruptible(
-			channel->playback_waitq,
-			kthread_should_stop() ||
-			(channel->is_stream_running &&
-			 (mbo = most_get_mbo(channel->iface, channel->id,
-					     &audio_aim))));
-		if (!mbo)
-			continue;
-
-		if (channel->is_stream_running)
-			period_elapsed = copy_data(channel, mbo);
-		else
-			memset(mbo->virt_address, 0, mbo->buffer_length);
-
-		most_submit_mbo(mbo);
-		if (period_elapsed)
-			snd_pcm_period_elapsed(channel->substream);
-	}
-
-	return 0;
-}
-
-/**
- * pcm_open - implements open callback function for PCM middle layer
- * @substream: pointer to ALSA PCM substream
- *
- * This is called when a PCM substream is opened. At least, the function should
- * initialize the runtime->hw record.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_open(struct snd_pcm_substream *substream)
-{
-	struct channel *channel = substream->private_data;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct most_channel_config *cfg = channel->cfg;
-
-	channel->substream = substream;
-
-	if (cfg->direction == MOST_CH_TX) {
-		channel->playback_task = kthread_run(playback_thread, channel,
-						     "most_audio_playback");
-		if (IS_ERR(channel->playback_task)) {
-			pr_err("Couldn't start thread\n");
-			return PTR_ERR(channel->playback_task);
-		}
-	}
-
-	if (most_start_channel(channel->iface, channel->id, &audio_aim)) {
-		pr_err("most_start_channel() failed!\n");
-		if (cfg->direction == MOST_CH_TX)
-			kthread_stop(channel->playback_task);
-		return -EBUSY;
-	}
-
-	runtime->hw = channel->pcm_hardware;
-	return 0;
-}
-
-/**
- * pcm_close - implements close callback function for PCM middle layer
- * @substream: sub-stream pointer
- *
- * Obviously, this is called when a PCM substream is closed. Any private
- * instance for a PCM substream allocated in the open callback will be
- * released here.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_close(struct snd_pcm_substream *substream)
-{
-	struct channel *channel = substream->private_data;
-
-	if (channel->cfg->direction == MOST_CH_TX)
-		kthread_stop(channel->playback_task);
-	most_stop_channel(channel->iface, channel->id, &audio_aim);
-
-	return 0;
-}
-
-/**
- * pcm_hw_params - implements hw_params callback function for PCM middle layer
- * @substream: sub-stream pointer
- * @hw_params: contains the hardware parameters set by the application
- *
- * This is called when the hardware parameters is set by the application, that
- * is, once when the buffer size, the period size, the format, etc. are defined
- * for the PCM substream. Many hardware setups should be done is this callback,
- * including the allocation of buffers.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_hw_params(struct snd_pcm_substream *substream,
-			 struct snd_pcm_hw_params *hw_params)
-{
-	struct channel *channel = substream->private_data;
-
-	if ((params_channels(hw_params) > channel->pcm_hardware.channels_max) ||
-	    (params_channels(hw_params) < channel->pcm_hardware.channels_min)) {
-		pr_err("Requested number of channels not supported.\n");
-		return -EINVAL;
-	}
-	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
-						params_buffer_bytes(hw_params));
-}
-
-/**
- * pcm_hw_free - implements hw_free callback function for PCM middle layer
- * @substream: substream pointer
- *
- * This is called to release the resources allocated via hw_params.
- * This function will be always called before the close callback is called.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_hw_free(struct snd_pcm_substream *substream)
-{
-	return snd_pcm_lib_free_vmalloc_buffer(substream);
-}
-
-/**
- * pcm_prepare - implements prepare callback function for PCM middle layer
- * @substream: substream pointer
- *
- * This callback is called when the PCM is "prepared". Format rate, sample rate,
- * etc., can be set here. This callback can be called many times at each setup.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_prepare(struct snd_pcm_substream *substream)
-{
-	struct channel *channel = substream->private_data;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct most_channel_config *cfg = channel->cfg;
-	int width = snd_pcm_format_physical_width(runtime->format);
-
-	channel->copy_fn = NULL;
-
-	if (cfg->direction == MOST_CH_TX) {
-		if (snd_pcm_format_big_endian(runtime->format) || width == 8)
-			channel->copy_fn = alsa_to_most_memcpy;
-		else if (width == 16)
-			channel->copy_fn = alsa_to_most_copy16;
-		else if (width == 24)
-			channel->copy_fn = alsa_to_most_copy24;
-		else if (width == 32)
-			channel->copy_fn = alsa_to_most_copy32;
-	} else {
-		if (snd_pcm_format_big_endian(runtime->format) || width == 8)
-			channel->copy_fn = most_to_alsa_memcpy;
-		else if (width == 16)
-			channel->copy_fn = most_to_alsa_copy16;
-		else if (width == 24)
-			channel->copy_fn = most_to_alsa_copy24;
-		else if (width == 32)
-			channel->copy_fn = most_to_alsa_copy32;
-	}
-
-	if (!channel->copy_fn) {
-		pr_err("unsupported format\n");
-		return -EINVAL;
-	}
-
-	channel->period_pos = 0;
-	channel->buffer_pos = 0;
-
-	return 0;
-}
-
-/**
- * pcm_trigger - implements trigger callback function for PCM middle layer
- * @substream: substream pointer
- * @cmd: action to perform
- *
- * This is called when the PCM is started, stopped or paused. The action will be
- * specified in the second argument, SNDRV_PCM_TRIGGER_XXX
- *
- * Returns 0 on success or error code otherwise.
- */
-static int pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct channel *channel = substream->private_data;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		channel->is_stream_running = true;
-		wake_up_interruptible(&channel->playback_waitq);
-		return 0;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-		channel->is_stream_running = false;
-		return 0;
-
-	default:
-		pr_info("%s(), invalid\n", __func__);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/**
- * pcm_pointer - implements pointer callback function for PCM middle layer
- * @substream: substream pointer
- *
- * This callback is called when the PCM middle layer inquires the current
- * hardware position on the buffer. The position must be returned in frames,
- * ranging from 0 to buffer_size-1.
- */
-static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream)
-{
-	struct channel *channel = substream->private_data;
-
-	return channel->buffer_pos;
-}
-
-/**
- * Initialization of struct snd_pcm_ops
- */
-static const struct snd_pcm_ops pcm_ops = {
-	.open       = pcm_open,
-	.close      = pcm_close,
-	.ioctl      = snd_pcm_lib_ioctl,
-	.hw_params  = pcm_hw_params,
-	.hw_free    = pcm_hw_free,
-	.prepare    = pcm_prepare,
-	.trigger    = pcm_trigger,
-	.pointer    = pcm_pointer,
-	.page       = snd_pcm_lib_get_vmalloc_page,
-	.mmap       = snd_pcm_lib_mmap_vmalloc,
-};
-
-static int split_arg_list(char *buf, char **card_name, char **pcm_format)
-{
-	*card_name = strsep(&buf, ".");
-	if (!*card_name)
-		return -EIO;
-	*pcm_format = strsep(&buf, ".\n");
-	if (!*pcm_format)
-		return -EIO;
-	return 0;
-}
-
-static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw,
-			       char *pcm_format,
-			       struct most_channel_config *cfg)
-{
-	pcm_hw->info = MOST_PCM_INFO;
-	pcm_hw->rates = SNDRV_PCM_RATE_48000;
-	pcm_hw->rate_min = 48000;
-	pcm_hw->rate_max = 48000;
-	pcm_hw->buffer_bytes_max = cfg->num_buffers * cfg->buffer_size;
-	pcm_hw->period_bytes_min = cfg->buffer_size;
-	pcm_hw->period_bytes_max = cfg->buffer_size;
-	pcm_hw->periods_min = 1;
-	pcm_hw->periods_max = cfg->num_buffers;
-
-	if (!strcmp(pcm_format, "1x8")) {
-		if (cfg->subbuffer_size != 1)
-			goto error;
-		pr_info("PCM format is 8-bit mono\n");
-		pcm_hw->channels_min = 1;
-		pcm_hw->channels_max = 1;
-		pcm_hw->formats = SNDRV_PCM_FMTBIT_S8;
-	} else if (!strcmp(pcm_format, "2x16")) {
-		if (cfg->subbuffer_size != 4)
-			goto error;
-		pr_info("PCM format is 16-bit stereo\n");
-		pcm_hw->channels_min = 2;
-		pcm_hw->channels_max = 2;
-		pcm_hw->formats = SNDRV_PCM_FMTBIT_S16_LE |
-				  SNDRV_PCM_FMTBIT_S16_BE;
-	} else if (!strcmp(pcm_format, "2x24")) {
-		if (cfg->subbuffer_size != 6)
-			goto error;
-		pr_info("PCM format is 24-bit stereo\n");
-		pcm_hw->channels_min = 2;
-		pcm_hw->channels_max = 2;
-		pcm_hw->formats = SNDRV_PCM_FMTBIT_S24_3LE |
-				  SNDRV_PCM_FMTBIT_S24_3BE;
-	} else if (!strcmp(pcm_format, "2x32")) {
-		if (cfg->subbuffer_size != 8)
-			goto error;
-		pr_info("PCM format is 32-bit stereo\n");
-		pcm_hw->channels_min = 2;
-		pcm_hw->channels_max = 2;
-		pcm_hw->formats = SNDRV_PCM_FMTBIT_S32_LE |
-				  SNDRV_PCM_FMTBIT_S32_BE;
-	} else if (!strcmp(pcm_format, "6x16")) {
-		if (cfg->subbuffer_size != 12)
-			goto error;
-		pr_info("PCM format is 16-bit 5.1 multi channel\n");
-		pcm_hw->channels_min = 6;
-		pcm_hw->channels_max = 6;
-		pcm_hw->formats = SNDRV_PCM_FMTBIT_S16_LE |
-				  SNDRV_PCM_FMTBIT_S16_BE;
-	} else {
-		pr_err("PCM format %s not supported\n", pcm_format);
-		return -EIO;
-	}
-	return 0;
-error:
-	pr_err("Audio resolution doesn't fit subbuffer size\n");
-	return -EINVAL;
-}
-
-/**
- * audio_probe_channel - probe function of the driver module
- * @iface: pointer to interface instance
- * @channel_id: channel index/ID
- * @cfg: pointer to actual channel configuration
- * @parent: pointer to kobject (needed for sysfs hook-up)
- * @arg_list: string that provides the name of the device to be created in /dev
- *	      plus the desired audio resolution
- *
- * Creates sound card, pcm device, sets pcm ops and registers sound card.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int audio_probe_channel(struct most_interface *iface, int channel_id,
-			       struct most_channel_config *cfg,
-			       struct kobject *parent, char *arg_list)
-{
-	struct channel *channel;
-	struct snd_card *card;
-	struct snd_pcm *pcm;
-	int playback_count = 0;
-	int capture_count = 0;
-	int ret;
-	int direction;
-	char *card_name;
-	char *pcm_format;
-
-	if (!iface)
-		return -EINVAL;
-
-	if (cfg->data_type != MOST_CH_SYNC) {
-		pr_err("Incompatible channel type\n");
-		return -EINVAL;
-	}
-
-	if (get_channel(iface, channel_id)) {
-		pr_err("channel (%s:%d) is already linked\n",
-		       iface->description, channel_id);
-		return -EINVAL;
-	}
-
-	if (cfg->direction == MOST_CH_TX) {
-		playback_count = 1;
-		direction = SNDRV_PCM_STREAM_PLAYBACK;
-	} else {
-		capture_count = 1;
-		direction = SNDRV_PCM_STREAM_CAPTURE;
-	}
-
-	ret = split_arg_list(arg_list, &card_name, &pcm_format);
-	if (ret < 0) {
-		pr_info("PCM format missing\n");
-		return ret;
-	}
-
-	ret = snd_card_new(NULL, -1, card_name, THIS_MODULE,
-			   sizeof(*channel), &card);
-	if (ret < 0)
-		return ret;
-
-	channel = card->private_data;
-	channel->card = card;
-	channel->cfg = cfg;
-	channel->iface = iface;
-	channel->id = channel_id;
-	init_waitqueue_head(&channel->playback_waitq);
-
-	ret = audio_set_hw_params(&channel->pcm_hardware, pcm_format, cfg);
-	if (ret)
-		goto err_free_card;
-
-	snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME);
-	snprintf(card->shortname, sizeof(card->shortname), "Microchip MOST:%d",
-		 card->number);
-	snprintf(card->longname, sizeof(card->longname), "%s at %s, ch %d",
-		 card->shortname, iface->description, channel_id);
-
-	ret = snd_pcm_new(card, card_name, 0, playback_count,
-			  capture_count, &pcm);
-	if (ret < 0)
-		goto err_free_card;
-
-	pcm->private_data = channel;
-
-	snd_pcm_set_ops(pcm, direction, &pcm_ops);
-
-	ret = snd_card_register(card);
-	if (ret < 0)
-		goto err_free_card;
-
-	list_add_tail(&channel->list, &dev_list);
-
-	return 0;
-
-err_free_card:
-	snd_card_free(card);
-	return ret;
-}
-
-/**
- * audio_disconnect_channel - function to disconnect a channel
- * @iface: pointer to interface instance
- * @channel_id: channel index
- *
- * This frees allocated memory and removes the sound card from ALSA
- *
- * Returns 0 on success or error code otherwise.
- */
-static int audio_disconnect_channel(struct most_interface *iface,
-				    int channel_id)
-{
-	struct channel *channel;
-
-	channel = get_channel(iface, channel_id);
-	if (!channel) {
-		pr_err("sound_disconnect_channel(), invalid channel %d\n",
-		       channel_id);
-		return -EINVAL;
-	}
-
-	list_del(&channel->list);
-	snd_card_free(channel->card);
-
-	return 0;
-}
-
-/**
- * audio_rx_completion - completion handler for rx channels
- * @mbo: pointer to buffer object that has completed
- *
- * This searches for the channel this MBO belongs to and copy the data from MBO
- * to ring buffer
- *
- * Returns 0 on success or error code otherwise.
- */
-static int audio_rx_completion(struct mbo *mbo)
-{
-	struct channel *channel = get_channel(mbo->ifp, mbo->hdm_channel_id);
-	bool period_elapsed = false;
-
-	if (!channel) {
-		pr_err("sound_rx_completion(), invalid channel %d\n",
-		       mbo->hdm_channel_id);
-		return -EINVAL;
-	}
-
-	if (channel->is_stream_running)
-		period_elapsed = copy_data(channel, mbo);
-
-	most_put_mbo(mbo);
-
-	if (period_elapsed)
-		snd_pcm_period_elapsed(channel->substream);
-
-	return 0;
-}
-
-/**
- * audio_tx_completion - completion handler for tx channels
- * @iface: pointer to interface instance
- * @channel_id: channel index/ID
- *
- * This searches the channel that belongs to this combination of interface
- * pointer and channel ID and wakes a process sitting in the wait queue of
- * this channel.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int audio_tx_completion(struct most_interface *iface, int channel_id)
-{
-	struct channel *channel = get_channel(iface, channel_id);
-
-	if (!channel) {
-		pr_err("sound_tx_completion(), invalid channel %d\n",
-		       channel_id);
-		return -EINVAL;
-	}
-
-	wake_up_interruptible(&channel->playback_waitq);
-
-	return 0;
-}
-
-/**
- * Initialization of the struct most_aim
- */
-static struct most_aim audio_aim = {
-	.name = DRIVER_NAME,
-	.probe_channel = audio_probe_channel,
-	.disconnect_channel = audio_disconnect_channel,
-	.rx_completion = audio_rx_completion,
-	.tx_completion = audio_tx_completion,
-};
-
-static int __init audio_init(void)
-{
-	pr_info("init()\n");
-
-	INIT_LIST_HEAD(&dev_list);
-
-	return most_register_aim(&audio_aim);
-}
-
-static void __exit audio_exit(void)
-{
-	struct channel *channel, *tmp;
-
-	pr_info("exit()\n");
-
-	list_for_each_entry_safe(channel, tmp, &dev_list, list) {
-		list_del(&channel->list);
-		snd_card_free(channel->card);
-	}
-
-	most_deregister_aim(&audio_aim);
-}
-
-module_init(audio_init);
-module_exit(audio_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
-MODULE_DESCRIPTION("Audio Application Interface Module for MostCore");
diff --git a/drivers/staging/most/aim-v4l2/Kconfig b/drivers/staging/most/aim-v4l2/Kconfig
deleted file mode 100644
index d70eaaf..0000000
--- a/drivers/staging/most/aim-v4l2/Kconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# MOST V4L2 configuration
-#
-
-config AIM_V4L2
-	tristate "V4L2 AIM"
-	depends on VIDEO_V4L2
-	---help---
-	  Say Y here if you want to commumicate via Video 4 Linux.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called aim_v4l2.
\ No newline at end of file
diff --git a/drivers/staging/most/aim-v4l2/Makefile b/drivers/staging/most/aim-v4l2/Makefile
deleted file mode 100644
index 69a7524..0000000
--- a/drivers/staging/most/aim-v4l2/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-obj-$(CONFIG_AIM_V4L2) += aim_v4l2.o
-
-aim_v4l2-objs := video.o
-
-ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c
deleted file mode 100644
index e074841..0000000
--- a/drivers/staging/most/aim-v4l2/video.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- * V4L2 AIM - V4L2 Application Interface Module for MostCore
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/suspend.h>
-#include <linux/videodev2.h>
-#include <linux/mutex.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fh.h>
-
-#include "mostcore.h"
-
-#define V4L2_AIM_MAX_INPUT  1
-
-static struct most_aim aim_info;
-
-struct most_video_dev {
-	struct most_interface *iface;
-	int ch_idx;
-	struct list_head list;
-	bool mute;
-
-	struct list_head pending_mbos;
-	spinlock_t list_lock;
-
-	struct v4l2_device v4l2_dev;
-	atomic_t access_ref;
-	struct video_device *vdev;
-	unsigned int ctrl_input;
-
-	struct mutex lock;
-
-	wait_queue_head_t wait_data;
-};
-
-struct aim_fh {
-	/* must be the first field of this struct! */
-	struct v4l2_fh fh;
-	struct most_video_dev *mdev;
-	u32 offs;
-};
-
-static struct list_head video_devices = LIST_HEAD_INIT(video_devices);
-static struct spinlock list_lock;
-
-static inline bool data_ready(struct most_video_dev *mdev)
-{
-	return !list_empty(&mdev->pending_mbos);
-}
-
-static inline struct mbo *get_top_mbo(struct most_video_dev *mdev)
-{
-	return list_first_entry(&mdev->pending_mbos, struct mbo, list);
-}
-
-static int aim_vdev_open(struct file *filp)
-{
-	int ret;
-	struct video_device *vdev = video_devdata(filp);
-	struct most_video_dev *mdev = video_drvdata(filp);
-	struct aim_fh *fh;
-
-	v4l2_info(&mdev->v4l2_dev, "aim_vdev_open()\n");
-
-	switch (vdev->vfl_type) {
-	case VFL_TYPE_GRABBER:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (!fh)
-		return -ENOMEM;
-
-	if (!atomic_inc_and_test(&mdev->access_ref)) {
-		v4l2_err(&mdev->v4l2_dev, "too many clients\n");
-		ret = -EBUSY;
-		goto err_dec;
-	}
-
-	fh->mdev = mdev;
-	v4l2_fh_init(&fh->fh, vdev);
-	filp->private_data = fh;
-
-	v4l2_fh_add(&fh->fh);
-
-	ret = most_start_channel(mdev->iface, mdev->ch_idx, &aim_info);
-	if (ret) {
-		v4l2_err(&mdev->v4l2_dev, "most_start_channel() failed\n");
-		goto err_rm;
-	}
-
-	return 0;
-
-err_rm:
-	v4l2_fh_del(&fh->fh);
-	v4l2_fh_exit(&fh->fh);
-
-err_dec:
-	atomic_dec(&mdev->access_ref);
-	kfree(fh);
-	return ret;
-}
-
-static int aim_vdev_close(struct file *filp)
-{
-	struct aim_fh *fh = filp->private_data;
-	struct most_video_dev *mdev = fh->mdev;
-	struct mbo *mbo, *tmp;
-
-	v4l2_info(&mdev->v4l2_dev, "aim_vdev_close()\n");
-
-	/*
-	 * We need to put MBOs back before we call most_stop_channel()
-	 * to deallocate MBOs.
-	 * From the other hand mostcore still calling rx_completion()
-	 * to deliver MBOs until most_stop_channel() is called.
-	 * Use mute to work around this issue.
-	 * This must be implemented in core.
-	 */
-
-	spin_lock_irq(&mdev->list_lock);
-	mdev->mute = true;
-	list_for_each_entry_safe(mbo, tmp, &mdev->pending_mbos, list) {
-		list_del(&mbo->list);
-		spin_unlock_irq(&mdev->list_lock);
-		most_put_mbo(mbo);
-		spin_lock_irq(&mdev->list_lock);
-	}
-	spin_unlock_irq(&mdev->list_lock);
-	most_stop_channel(mdev->iface, mdev->ch_idx, &aim_info);
-	mdev->mute = false;
-
-	v4l2_fh_del(&fh->fh);
-	v4l2_fh_exit(&fh->fh);
-
-	atomic_dec(&mdev->access_ref);
-	kfree(fh);
-	return 0;
-}
-
-static ssize_t aim_vdev_read(struct file *filp, char __user *buf,
-			     size_t count, loff_t *pos)
-{
-	struct aim_fh *fh = filp->private_data;
-	struct most_video_dev *mdev = fh->mdev;
-	int ret = 0;
-
-	if (*pos)
-		return -ESPIPE;
-
-	if (!mdev)
-		return -ENODEV;
-
-	/* wait for the first buffer */
-	if (!(filp->f_flags & O_NONBLOCK)) {
-		if (wait_event_interruptible(mdev->wait_data, data_ready(mdev)))
-			return -ERESTARTSYS;
-	}
-
-	if (!data_ready(mdev))
-		return -EAGAIN;
-
-	while (count > 0 && data_ready(mdev)) {
-		struct mbo *const mbo = get_top_mbo(mdev);
-		int const rem = mbo->processed_length - fh->offs;
-		int const cnt = rem < count ? rem : count;
-
-		if (copy_to_user(buf, mbo->virt_address + fh->offs, cnt)) {
-			v4l2_err(&mdev->v4l2_dev, "read: copy_to_user failed\n");
-			if (!ret)
-				ret = -EFAULT;
-			return ret;
-		}
-
-		fh->offs += cnt;
-		count -= cnt;
-		buf += cnt;
-		ret += cnt;
-
-		if (cnt >= rem) {
-			fh->offs = 0;
-			spin_lock_irq(&mdev->list_lock);
-			list_del(&mbo->list);
-			spin_unlock_irq(&mdev->list_lock);
-			most_put_mbo(mbo);
-		}
-	}
-	return ret;
-}
-
-static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait)
-{
-	struct aim_fh *fh = filp->private_data;
-	struct most_video_dev *mdev = fh->mdev;
-	unsigned int mask = 0;
-
-	/* only wait if no data is available */
-	if (!data_ready(mdev))
-		poll_wait(filp, &mdev->wait_data, wait);
-	if (data_ready(mdev))
-		mask |= POLLIN | POLLRDNORM;
-
-	return mask;
-}
-
-static void aim_set_format_struct(struct v4l2_format *f)
-{
-	f->fmt.pix.width = 8;
-	f->fmt.pix.height = 8;
-	f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
-	f->fmt.pix.bytesperline = 0;
-	f->fmt.pix.sizeimage = 188 * 2;
-	f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
-	f->fmt.pix.field = V4L2_FIELD_NONE;
-	f->fmt.pix.priv = 0;
-}
-
-static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd,
-			  struct v4l2_format *format)
-{
-	if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG)
-		return -EINVAL;
-
-	if (cmd == VIDIOC_TRY_FMT)
-		return 0;
-
-	aim_set_format_struct(format);
-
-	return 0;
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
-			   struct v4l2_capability *cap)
-{
-	struct aim_fh *fh = priv;
-	struct most_video_dev *mdev = fh->mdev;
-
-	v4l2_info(&mdev->v4l2_dev, "vidioc_querycap()\n");
-
-	strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver));
-	strlcpy(cap->card, "MOST", sizeof(cap->card));
-	snprintf(cap->bus_info, sizeof(cap->bus_info),
-		 "%s", mdev->iface->description);
-
-	cap->capabilities =
-		V4L2_CAP_READWRITE |
-		V4L2_CAP_TUNER |
-		V4L2_CAP_VIDEO_CAPTURE;
-	return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
-				   struct v4l2_fmtdesc *f)
-{
-	struct aim_fh *fh = priv;
-	struct most_video_dev *mdev = fh->mdev;
-
-	v4l2_info(&mdev->v4l2_dev, "vidioc_enum_fmt_vid_cap() %d\n", f->index);
-
-	if (f->index)
-		return -EINVAL;
-
-	strcpy(f->description, "MPEG");
-	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	f->flags = V4L2_FMT_FLAG_COMPRESSED;
-	f->pixelformat = V4L2_PIX_FMT_MPEG;
-
-	return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-				struct v4l2_format *f)
-{
-	struct aim_fh *fh = priv;
-	struct most_video_dev *mdev = fh->mdev;
-
-	v4l2_info(&mdev->v4l2_dev, "vidioc_g_fmt_vid_cap()\n");
-
-	aim_set_format_struct(f);
-	return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-				  struct v4l2_format *f)
-{
-	struct aim_fh *fh = priv;
-	struct most_video_dev *mdev = fh->mdev;
-
-	return aim_set_format(mdev, VIDIOC_TRY_FMT, f);
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-				struct v4l2_format *f)
-{
-	struct aim_fh *fh = priv;
-	struct most_video_dev *mdev = fh->mdev;
-
-	return aim_set_format(mdev, VIDIOC_S_FMT, f);
-}
-
-static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
-{
-	struct aim_fh *fh = priv;
-	struct most_video_dev *mdev = fh->mdev;
-
-	v4l2_info(&mdev->v4l2_dev, "vidioc_g_std()\n");
-
-	*norm = V4L2_STD_UNKNOWN;
-	return 0;
-}
-
-static int vidioc_enum_input(struct file *file, void *priv,
-			     struct v4l2_input *input)
-{
-	struct aim_fh *fh = priv;
-	struct most_video_dev *mdev = fh->mdev;
-
-	if (input->index >= V4L2_AIM_MAX_INPUT)
-		return -EINVAL;
-
-	strcpy(input->name, "MOST Video");
-	input->type |= V4L2_INPUT_TYPE_CAMERA;
-	input->audioset = 0;
-
-	input->std = mdev->vdev->tvnorms;
-
-	return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-	struct aim_fh *fh = priv;
-	struct most_video_dev *mdev = fh->mdev;
-	*i = mdev->ctrl_input;
-	return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
-{
-	struct aim_fh *fh = priv;
-	struct most_video_dev *mdev = fh->mdev;
-
-	v4l2_info(&mdev->v4l2_dev, "vidioc_s_input(%d)\n", index);
-
-	if (index >= V4L2_AIM_MAX_INPUT)
-		return -EINVAL;
-	mdev->ctrl_input = index;
-	return 0;
-}
-
-static const struct v4l2_file_operations aim_fops = {
-	.owner      = THIS_MODULE,
-	.open       = aim_vdev_open,
-	.release    = aim_vdev_close,
-	.read       = aim_vdev_read,
-	.poll       = aim_vdev_poll,
-	.unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops video_ioctl_ops = {
-	.vidioc_querycap            = vidioc_querycap,
-	.vidioc_enum_fmt_vid_cap    = vidioc_enum_fmt_vid_cap,
-	.vidioc_g_fmt_vid_cap       = vidioc_g_fmt_vid_cap,
-	.vidioc_try_fmt_vid_cap     = vidioc_try_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
-	.vidioc_g_std               = vidioc_g_std,
-	.vidioc_enum_input          = vidioc_enum_input,
-	.vidioc_g_input             = vidioc_g_input,
-	.vidioc_s_input             = vidioc_s_input,
-};
-
-static const struct video_device aim_videodev_template = {
-	.fops = &aim_fops,
-	.release = video_device_release,
-	.ioctl_ops = &video_ioctl_ops,
-	.tvnorms = V4L2_STD_UNKNOWN,
-};
-
-/**************************************************************************/
-
-static struct most_video_dev *get_aim_dev(
-	struct most_interface *iface, int channel_idx)
-{
-	struct most_video_dev *mdev;
-	unsigned long flags;
-
-	spin_lock_irqsave(&list_lock, flags);
-	list_for_each_entry(mdev, &video_devices, list) {
-		if (mdev->iface == iface && mdev->ch_idx == channel_idx) {
-			spin_unlock_irqrestore(&list_lock, flags);
-			return mdev;
-		}
-	}
-	spin_unlock_irqrestore(&list_lock, flags);
-	return NULL;
-}
-
-static int aim_rx_data(struct mbo *mbo)
-{
-	unsigned long flags;
-	struct most_video_dev *mdev =
-		get_aim_dev(mbo->ifp, mbo->hdm_channel_id);
-
-	if (!mdev)
-		return -EIO;
-
-	spin_lock_irqsave(&mdev->list_lock, flags);
-	if (unlikely(mdev->mute)) {
-		spin_unlock_irqrestore(&mdev->list_lock, flags);
-		return -EIO;
-	}
-
-	list_add_tail(&mbo->list, &mdev->pending_mbos);
-	spin_unlock_irqrestore(&mdev->list_lock, flags);
-	wake_up_interruptible(&mdev->wait_data);
-	return 0;
-}
-
-static int aim_register_videodev(struct most_video_dev *mdev)
-{
-	int ret;
-
-	v4l2_info(&mdev->v4l2_dev, "aim_register_videodev()\n");
-
-	init_waitqueue_head(&mdev->wait_data);
-
-	/* allocate and fill v4l2 video struct */
-	mdev->vdev = video_device_alloc();
-	if (!mdev->vdev)
-		return -ENOMEM;
-
-	/* Fill the video capture device struct */
-	*mdev->vdev = aim_videodev_template;
-	mdev->vdev->v4l2_dev = &mdev->v4l2_dev;
-	mdev->vdev->lock = &mdev->lock;
-	snprintf(mdev->vdev->name, sizeof(mdev->vdev->name), "MOST: %s",
-		 mdev->v4l2_dev.name);
-
-	/* Register the v4l2 device */
-	video_set_drvdata(mdev->vdev, mdev);
-	ret = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1);
-	if (ret) {
-		v4l2_err(&mdev->v4l2_dev, "video_register_device failed (%d)\n",
-			 ret);
-		video_device_release(mdev->vdev);
-	}
-
-	return ret;
-}
-
-static void aim_unregister_videodev(struct most_video_dev *mdev)
-{
-	v4l2_info(&mdev->v4l2_dev, "aim_unregister_videodev()\n");
-
-	video_unregister_device(mdev->vdev);
-}
-
-static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev)
-{
-	struct most_video_dev *mdev =
-		container_of(v4l2_dev, struct most_video_dev, v4l2_dev);
-
-	v4l2_device_unregister(v4l2_dev);
-	kfree(mdev);
-}
-
-static int aim_probe_channel(struct most_interface *iface, int channel_idx,
-			     struct most_channel_config *ccfg,
-			     struct kobject *parent, char *name)
-{
-	int ret;
-	struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
-
-	pr_info("aim_probe_channel(%s)\n", name);
-
-	if (mdev) {
-		pr_err("channel already linked\n");
-		return -EEXIST;
-	}
-
-	if (ccfg->direction != MOST_CH_RX) {
-		pr_err("wrong direction, expect rx\n");
-		return -EINVAL;
-	}
-
-	if (ccfg->data_type != MOST_CH_SYNC &&
-	    ccfg->data_type != MOST_CH_ISOC) {
-		pr_err("wrong channel type, expect sync or isoc\n");
-		return -EINVAL;
-	}
-
-	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
-	if (!mdev)
-		return -ENOMEM;
-
-	mutex_init(&mdev->lock);
-	atomic_set(&mdev->access_ref, -1);
-	spin_lock_init(&mdev->list_lock);
-	INIT_LIST_HEAD(&mdev->pending_mbos);
-	mdev->iface = iface;
-	mdev->ch_idx = channel_idx;
-	mdev->v4l2_dev.release = aim_v4l2_dev_release;
-
-	/* Create the v4l2_device */
-	strlcpy(mdev->v4l2_dev.name, name, sizeof(mdev->v4l2_dev.name));
-	ret = v4l2_device_register(NULL, &mdev->v4l2_dev);
-	if (ret) {
-		pr_err("v4l2_device_register() failed\n");
-		kfree(mdev);
-		return ret;
-	}
-
-	ret = aim_register_videodev(mdev);
-	if (ret)
-		goto err_unreg;
-
-	spin_lock_irq(&list_lock);
-	list_add(&mdev->list, &video_devices);
-	spin_unlock_irq(&list_lock);
-	v4l2_info(&mdev->v4l2_dev, "aim_probe_channel() done\n");
-	return 0;
-
-err_unreg:
-	v4l2_device_disconnect(&mdev->v4l2_dev);
-	v4l2_device_put(&mdev->v4l2_dev);
-	return ret;
-}
-
-static int aim_disconnect_channel(struct most_interface *iface,
-				  int channel_idx)
-{
-	struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
-
-	if (!mdev) {
-		pr_err("no such channel is linked\n");
-		return -ENOENT;
-	}
-
-	v4l2_info(&mdev->v4l2_dev, "aim_disconnect_channel()\n");
-
-	spin_lock_irq(&list_lock);
-	list_del(&mdev->list);
-	spin_unlock_irq(&list_lock);
-
-	aim_unregister_videodev(mdev);
-	v4l2_device_disconnect(&mdev->v4l2_dev);
-	v4l2_device_put(&mdev->v4l2_dev);
-	return 0;
-}
-
-static struct most_aim aim_info = {
-	.name = "v4l",
-	.probe_channel = aim_probe_channel,
-	.disconnect_channel = aim_disconnect_channel,
-	.rx_completion = aim_rx_data,
-};
-
-static int __init aim_init(void)
-{
-	spin_lock_init(&list_lock);
-	return most_register_aim(&aim_info);
-}
-
-static void __exit aim_exit(void)
-{
-	struct most_video_dev *mdev, *tmp;
-
-	/*
-	 * As the mostcore currently doesn't call disconnect_channel()
-	 * for linked channels while we call most_deregister_aim()
-	 * we simulate this call here.
-	 * This must be fixed in core.
-	 */
-	spin_lock_irq(&list_lock);
-	list_for_each_entry_safe(mdev, tmp, &video_devices, list) {
-		list_del(&mdev->list);
-		spin_unlock_irq(&list_lock);
-
-		aim_unregister_videodev(mdev);
-		v4l2_device_disconnect(&mdev->v4l2_dev);
-		v4l2_device_put(&mdev->v4l2_dev);
-		spin_lock_irq(&list_lock);
-	}
-	spin_unlock_irq(&list_lock);
-
-	most_deregister_aim(&aim_info);
-	BUG_ON(!list_empty(&video_devices));
-}
-
-module_init(aim_init);
-module_exit(aim_exit);
-
-MODULE_DESCRIPTION("V4L2 Application Interface Module for MostCore");
-MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/cdev/Kconfig b/drivers/staging/most/cdev/Kconfig
new file mode 100644
index 0000000..2b04e26
--- /dev/null
+++ b/drivers/staging/most/cdev/Kconfig
@@ -0,0 +1,12 @@
+#
+# MOST Cdev configuration
+#
+
+config MOST_CDEV
+	tristate "Cdev"
+
+	---help---
+	  Say Y here if you want to commumicate via character devices.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called most_cdev.
diff --git a/drivers/staging/most/cdev/Makefile b/drivers/staging/most/cdev/Makefile
new file mode 100644
index 0000000..afb9870
--- /dev/null
+++ b/drivers/staging/most/cdev/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_CDEV) += most_cdev.o
+
+most_cdev-objs := cdev.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c
new file mode 100644
index 0000000..3dce5e0
--- /dev/null
+++ b/drivers/staging/most/cdev/cdev.c
@@ -0,0 +1,564 @@
+/*
+ * cdev.c - Application interfacing module for character devices
+ *
+ * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/poll.h>
+#include <linux/kfifo.h>
+#include <linux/uaccess.h>
+#include <linux/idr.h>
+#include <most/core.h>
+
+static dev_t aim_devno;
+static struct class *aim_class;
+static struct ida minor_id;
+static unsigned int major;
+static struct most_aim cdev_aim;
+
+struct aim_channel {
+	wait_queue_head_t wq;
+	spinlock_t unlink;	/* synchronization lock to unlink channels */
+	struct cdev cdev;
+	struct device *dev;
+	struct mutex io_mutex;
+	struct most_interface *iface;
+	struct most_channel_config *cfg;
+	unsigned int channel_id;
+	dev_t devno;
+	size_t mbo_offs;
+	DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *));
+	int access_ref;
+	struct list_head list;
+};
+
+#define to_channel(d) container_of(d, struct aim_channel, cdev)
+static struct list_head channel_list;
+static spinlock_t ch_list_lock;
+
+static inline bool ch_has_mbo(struct aim_channel *c)
+{
+	return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0;
+}
+
+static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo)
+{
+	if (!kfifo_peek(&c->fifo, mbo)) {
+		*mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim);
+		if (*mbo)
+			kfifo_in(&c->fifo, mbo, 1);
+	}
+	return *mbo;
+}
+
+static struct aim_channel *get_channel(struct most_interface *iface, int id)
+{
+	struct aim_channel *c, *tmp;
+	unsigned long flags;
+	int found_channel = 0;
+
+	spin_lock_irqsave(&ch_list_lock, flags);
+	list_for_each_entry_safe(c, tmp, &channel_list, list) {
+		if ((c->iface == iface) && (c->channel_id == id)) {
+			found_channel = 1;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&ch_list_lock, flags);
+	if (!found_channel)
+		return NULL;
+	return c;
+}
+
+static void stop_channel(struct aim_channel *c)
+{
+	struct mbo *mbo;
+
+	while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1))
+		most_put_mbo(mbo);
+	most_stop_channel(c->iface, c->channel_id, &cdev_aim);
+}
+
+static void destroy_cdev(struct aim_channel *c)
+{
+	unsigned long flags;
+
+	device_destroy(aim_class, c->devno);
+	cdev_del(&c->cdev);
+	spin_lock_irqsave(&ch_list_lock, flags);
+	list_del(&c->list);
+	spin_unlock_irqrestore(&ch_list_lock, flags);
+}
+
+static void destroy_channel(struct aim_channel *c)
+{
+	ida_simple_remove(&minor_id, MINOR(c->devno));
+	kfifo_free(&c->fifo);
+	kfree(c);
+}
+
+/**
+ * aim_open - implements the syscall to open the device
+ * @inode: inode pointer
+ * @filp: file pointer
+ *
+ * This stores the channel pointer in the private data field of
+ * the file structure and activates the channel within the core.
+ */
+static int aim_open(struct inode *inode, struct file *filp)
+{
+	struct aim_channel *c;
+	int ret;
+
+	c = to_channel(inode->i_cdev);
+	filp->private_data = c;
+
+	if (((c->cfg->direction == MOST_CH_RX) &&
+	     ((filp->f_flags & O_ACCMODE) != O_RDONLY)) ||
+	     ((c->cfg->direction == MOST_CH_TX) &&
+		((filp->f_flags & O_ACCMODE) != O_WRONLY))) {
+		pr_info("WARN: Access flags mismatch\n");
+		return -EACCES;
+	}
+
+	mutex_lock(&c->io_mutex);
+	if (!c->dev) {
+		pr_info("WARN: Device is destroyed\n");
+		mutex_unlock(&c->io_mutex);
+		return -ENODEV;
+	}
+
+	if (c->access_ref) {
+		pr_info("WARN: Device is busy\n");
+		mutex_unlock(&c->io_mutex);
+		return -EBUSY;
+	}
+
+	c->mbo_offs = 0;
+	ret = most_start_channel(c->iface, c->channel_id, &cdev_aim);
+	if (!ret)
+		c->access_ref = 1;
+	mutex_unlock(&c->io_mutex);
+	return ret;
+}
+
+/**
+ * aim_close - implements the syscall to close the device
+ * @inode: inode pointer
+ * @filp: file pointer
+ *
+ * This stops the channel within the core.
+ */
+static int aim_close(struct inode *inode, struct file *filp)
+{
+	struct aim_channel *c = to_channel(inode->i_cdev);
+
+	mutex_lock(&c->io_mutex);
+	spin_lock(&c->unlink);
+	c->access_ref = 0;
+	spin_unlock(&c->unlink);
+	if (c->dev) {
+		stop_channel(c);
+		mutex_unlock(&c->io_mutex);
+	} else {
+		mutex_unlock(&c->io_mutex);
+		destroy_channel(c);
+	}
+	return 0;
+}
+
+/**
+ * aim_write - implements the syscall to write to the device
+ * @filp: file pointer
+ * @buf: pointer to user buffer
+ * @count: number of bytes to write
+ * @offset: offset from where to start writing
+ */
+static ssize_t aim_write(struct file *filp, const char __user *buf,
+			 size_t count, loff_t *offset)
+{
+	int ret;
+	size_t to_copy, left;
+	struct mbo *mbo = NULL;
+	struct aim_channel *c = filp->private_data;
+
+	mutex_lock(&c->io_mutex);
+	while (c->dev && !ch_get_mbo(c, &mbo)) {
+		mutex_unlock(&c->io_mutex);
+
+		if ((filp->f_flags & O_NONBLOCK))
+			return -EAGAIN;
+		if (wait_event_interruptible(c->wq, ch_has_mbo(c) || !c->dev))
+			return -ERESTARTSYS;
+		mutex_lock(&c->io_mutex);
+	}
+
+	if (unlikely(!c->dev)) {
+		ret = -ENODEV;
+		goto unlock;
+	}
+
+	to_copy = min(count, c->cfg->buffer_size - c->mbo_offs);
+	left = copy_from_user(mbo->virt_address + c->mbo_offs, buf, to_copy);
+	if (left == to_copy) {
+		ret = -EFAULT;
+		goto unlock;
+	}
+
+	c->mbo_offs += to_copy - left;
+	if (c->mbo_offs >= c->cfg->buffer_size ||
+	    c->cfg->data_type == MOST_CH_CONTROL ||
+	    c->cfg->data_type == MOST_CH_ASYNC) {
+		kfifo_skip(&c->fifo);
+		mbo->buffer_length = c->mbo_offs;
+		c->mbo_offs = 0;
+		most_submit_mbo(mbo);
+	}
+
+	ret = to_copy - left;
+unlock:
+	mutex_unlock(&c->io_mutex);
+	return ret;
+}
+
+/**
+ * aim_read - implements the syscall to read from the device
+ * @filp: file pointer
+ * @buf: pointer to user buffer
+ * @count: number of bytes to read
+ * @offset: offset from where to start reading
+ */
+static ssize_t
+aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
+{
+	size_t to_copy, not_copied, copied;
+	struct mbo *mbo;
+	struct aim_channel *c = filp->private_data;
+
+	mutex_lock(&c->io_mutex);
+	while (c->dev && !kfifo_peek(&c->fifo, &mbo)) {
+		mutex_unlock(&c->io_mutex);
+		if (filp->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+		if (wait_event_interruptible(c->wq,
+					     (!kfifo_is_empty(&c->fifo) ||
+					      (!c->dev))))
+			return -ERESTARTSYS;
+		mutex_lock(&c->io_mutex);
+	}
+
+	/* make sure we don't submit to gone devices */
+	if (unlikely(!c->dev)) {
+		mutex_unlock(&c->io_mutex);
+		return -ENODEV;
+	}
+
+	to_copy = min_t(size_t,
+			count,
+			mbo->processed_length - c->mbo_offs);
+
+	not_copied = copy_to_user(buf,
+				  mbo->virt_address + c->mbo_offs,
+				  to_copy);
+
+	copied = to_copy - not_copied;
+
+	c->mbo_offs += copied;
+	if (c->mbo_offs >= mbo->processed_length) {
+		kfifo_skip(&c->fifo);
+		most_put_mbo(mbo);
+		c->mbo_offs = 0;
+	}
+	mutex_unlock(&c->io_mutex);
+	return copied;
+}
+
+static unsigned int aim_poll(struct file *filp, poll_table *wait)
+{
+	struct aim_channel *c = filp->private_data;
+	unsigned int mask = 0;
+
+	poll_wait(filp, &c->wq, wait);
+
+	if (c->cfg->direction == MOST_CH_RX) {
+		if (!kfifo_is_empty(&c->fifo))
+			mask |= POLLIN | POLLRDNORM;
+	} else {
+		if (!kfifo_is_empty(&c->fifo) || ch_has_mbo(c))
+			mask |= POLLOUT | POLLWRNORM;
+	}
+	return mask;
+}
+
+/**
+ * Initialization of struct file_operations
+ */
+static const struct file_operations channel_fops = {
+	.owner = THIS_MODULE,
+	.read = aim_read,
+	.write = aim_write,
+	.open = aim_open,
+	.release = aim_close,
+	.poll = aim_poll,
+};
+
+/**
+ * aim_disconnect_channel - disconnect a channel
+ * @iface: pointer to interface instance
+ * @channel_id: channel index
+ *
+ * This frees allocated memory and removes the cdev that represents this
+ * channel in user space.
+ */
+static int aim_disconnect_channel(struct most_interface *iface, int channel_id)
+{
+	struct aim_channel *c;
+
+	if (!iface) {
+		pr_info("Bad interface pointer\n");
+		return -EINVAL;
+	}
+
+	c = get_channel(iface, channel_id);
+	if (!c)
+		return -ENXIO;
+
+	mutex_lock(&c->io_mutex);
+	spin_lock(&c->unlink);
+	c->dev = NULL;
+	spin_unlock(&c->unlink);
+	destroy_cdev(c);
+	if (c->access_ref) {
+		stop_channel(c);
+		wake_up_interruptible(&c->wq);
+		mutex_unlock(&c->io_mutex);
+	} else {
+		mutex_unlock(&c->io_mutex);
+		destroy_channel(c);
+	}
+	return 0;
+}
+
+/**
+ * aim_rx_completion - completion handler for rx channels
+ * @mbo: pointer to buffer object that has completed
+ *
+ * This searches for the channel linked to this MBO and stores it in the local
+ * fifo buffer.
+ */
+static int aim_rx_completion(struct mbo *mbo)
+{
+	struct aim_channel *c;
+
+	if (!mbo)
+		return -EINVAL;
+
+	c = get_channel(mbo->ifp, mbo->hdm_channel_id);
+	if (!c)
+		return -ENXIO;
+
+	spin_lock(&c->unlink);
+	if (!c->access_ref || !c->dev) {
+		spin_unlock(&c->unlink);
+		return -ENODEV;
+	}
+	kfifo_in(&c->fifo, &mbo, 1);
+	spin_unlock(&c->unlink);
+#ifdef DEBUG_MESG
+	if (kfifo_is_full(&c->fifo))
+		pr_info("WARN: Fifo is full\n");
+#endif
+	wake_up_interruptible(&c->wq);
+	return 0;
+}
+
+/**
+ * aim_tx_completion - completion handler for tx channels
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ *
+ * This wakes sleeping processes in the wait-queue.
+ */
+static int aim_tx_completion(struct most_interface *iface, int channel_id)
+{
+	struct aim_channel *c;
+
+	if (!iface) {
+		pr_info("Bad interface pointer\n");
+		return -EINVAL;
+	}
+	if ((channel_id < 0) || (channel_id >= iface->num_channels)) {
+		pr_info("Channel ID out of range\n");
+		return -EINVAL;
+	}
+
+	c = get_channel(iface, channel_id);
+	if (!c)
+		return -ENXIO;
+	wake_up_interruptible(&c->wq);
+	return 0;
+}
+
+/**
+ * aim_probe - probe function of the driver module
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ * @cfg: pointer to actual channel configuration
+ * @parent: pointer to kobject (needed for sysfs hook-up)
+ * @name: name of the device to be created
+ *
+ * This allocates achannel object and creates the device node in /dev
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int aim_probe(struct most_interface *iface, int channel_id,
+		     struct most_channel_config *cfg,
+		     struct kobject *parent, char *name)
+{
+	struct aim_channel *c;
+	unsigned long cl_flags;
+	int retval;
+	int current_minor;
+
+	if ((!iface) || (!cfg) || (!parent) || (!name)) {
+		pr_info("Probing AIM with bad arguments");
+		return -EINVAL;
+	}
+	c = get_channel(iface, channel_id);
+	if (c)
+		return -EEXIST;
+
+	current_minor = ida_simple_get(&minor_id, 0, 0, GFP_KERNEL);
+	if (current_minor < 0)
+		return current_minor;
+
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
+	if (!c) {
+		retval = -ENOMEM;
+		goto error_alloc_channel;
+	}
+
+	c->devno = MKDEV(major, current_minor);
+	cdev_init(&c->cdev, &channel_fops);
+	c->cdev.owner = THIS_MODULE;
+	cdev_add(&c->cdev, c->devno, 1);
+	c->iface = iface;
+	c->cfg = cfg;
+	c->channel_id = channel_id;
+	c->access_ref = 0;
+	spin_lock_init(&c->unlink);
+	INIT_KFIFO(c->fifo);
+	retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL);
+	if (retval) {
+		pr_info("failed to alloc channel kfifo");
+		goto error_alloc_kfifo;
+	}
+	init_waitqueue_head(&c->wq);
+	mutex_init(&c->io_mutex);
+	spin_lock_irqsave(&ch_list_lock, cl_flags);
+	list_add_tail(&c->list, &channel_list);
+	spin_unlock_irqrestore(&ch_list_lock, cl_flags);
+	c->dev = device_create(aim_class,
+				     NULL,
+				     c->devno,
+				     NULL,
+				     "%s", name);
+
+	if (IS_ERR(c->dev)) {
+		retval = PTR_ERR(c->dev);
+		pr_info("failed to create new device node %s\n", name);
+		goto error_create_device;
+	}
+	kobject_uevent(&c->dev->kobj, KOBJ_ADD);
+	return 0;
+
+error_create_device:
+	kfifo_free(&c->fifo);
+	list_del(&c->list);
+error_alloc_kfifo:
+	cdev_del(&c->cdev);
+	kfree(c);
+error_alloc_channel:
+	ida_simple_remove(&minor_id, current_minor);
+	return retval;
+}
+
+static struct most_aim cdev_aim = {
+	.name = "cdev",
+	.probe_channel = aim_probe,
+	.disconnect_channel = aim_disconnect_channel,
+	.rx_completion = aim_rx_completion,
+	.tx_completion = aim_tx_completion,
+};
+
+static int __init mod_init(void)
+{
+	int err;
+
+	pr_info("init()\n");
+
+	INIT_LIST_HEAD(&channel_list);
+	spin_lock_init(&ch_list_lock);
+	ida_init(&minor_id);
+
+	err = alloc_chrdev_region(&aim_devno, 0, 50, "cdev");
+	if (err < 0)
+		goto dest_ida;
+	major = MAJOR(aim_devno);
+
+	aim_class = class_create(THIS_MODULE, "most_cdev_aim");
+	if (IS_ERR(aim_class)) {
+		pr_err("no udev support\n");
+		err = PTR_ERR(aim_class);
+		goto free_cdev;
+	}
+	err = most_register_aim(&cdev_aim);
+	if (err)
+		goto dest_class;
+	return 0;
+
+dest_class:
+	class_destroy(aim_class);
+free_cdev:
+	unregister_chrdev_region(aim_devno, 1);
+dest_ida:
+	ida_destroy(&minor_id);
+	return err;
+}
+
+static void __exit mod_exit(void)
+{
+	struct aim_channel *c, *tmp;
+
+	pr_info("exit module\n");
+
+	most_deregister_aim(&cdev_aim);
+
+	list_for_each_entry_safe(c, tmp, &channel_list, list) {
+		destroy_cdev(c);
+		destroy_channel(c);
+	}
+	class_destroy(aim_class);
+	unregister_chrdev_region(aim_devno, 1);
+	ida_destroy(&minor_id);
+}
+
+module_init(mod_init);
+module_exit(mod_exit);
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("character device AIM for mostcore");
diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
new file mode 100644
index 0000000..6ee6acf
--- /dev/null
+++ b/drivers/staging/most/core.c
@@ -0,0 +1,1949 @@
+/*
+ * core.c - Implementation of core module of MOST Linux driver stack
+ *
+ * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/kobject.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/sysfs.h>
+#include <linux/kthread.h>
+#include <linux/dma-mapping.h>
+#include <linux/idr.h>
+#include <most/core.h>
+
+#define MAX_CHANNELS	64
+#define STRING_SIZE	80
+
+static struct class *most_class;
+static struct device *core_dev;
+static struct ida mdev_id;
+static int dummy_num_buffers;
+
+struct most_c_aim_obj {
+	struct most_aim *ptr;
+	int refs;
+	int num_buffers;
+};
+
+struct most_c_obj {
+	struct kobject kobj;
+	struct completion cleanup;
+	atomic_t mbo_ref;
+	atomic_t mbo_nq_level;
+	u16 channel_id;
+	bool is_poisoned;
+	struct mutex start_mutex;
+	struct mutex nq_mutex; /* nq thread synchronization */
+	int is_starving;
+	struct most_interface *iface;
+	struct most_inst_obj *inst;
+	struct most_channel_config cfg;
+	bool keep_mbo;
+	bool enqueue_halt;
+	struct list_head fifo;
+	spinlock_t fifo_lock;
+	struct list_head halt_fifo;
+	struct list_head list;
+	struct most_c_aim_obj aim0;
+	struct most_c_aim_obj aim1;
+	struct list_head trash_fifo;
+	struct task_struct *hdm_enqueue_task;
+	wait_queue_head_t hdm_fifo_wq;
+};
+
+#define to_c_obj(d) container_of(d, struct most_c_obj, kobj)
+
+struct most_inst_obj {
+	int dev_id;
+	struct most_interface *iface;
+	struct list_head channel_list;
+	struct most_c_obj *channel[MAX_CHANNELS];
+	struct kobject kobj;
+	struct list_head list;
+};
+
+static const struct {
+	int most_ch_data_type;
+	const char *name;
+} ch_data_type[] = {
+	{ MOST_CH_CONTROL, "control\n" },
+	{ MOST_CH_ASYNC, "async\n" },
+	{ MOST_CH_SYNC, "sync\n" },
+	{ MOST_CH_ISOC, "isoc\n"},
+	{ MOST_CH_ISOC, "isoc_avp\n"},
+};
+
+#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj)
+
+/**
+ * list_pop_mbo - retrieves the first MBO of the list and removes it
+ * @ptr: the list head to grab the MBO from.
+ */
+#define list_pop_mbo(ptr)						\
+({									\
+	struct mbo *_mbo = list_first_entry(ptr, struct mbo, list);	\
+	list_del(&_mbo->list);						\
+	_mbo;								\
+})
+
+/*		     ___	     ___
+ *		     ___C H A N N E L___
+ */
+
+/**
+ * struct most_c_attr - to access the attributes of a channel object
+ * @attr: attributes of a channel
+ * @show: pointer to the show function
+ * @store: pointer to the store function
+ */
+struct most_c_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct most_c_obj *d,
+			struct most_c_attr *attr,
+			char *buf);
+	ssize_t (*store)(struct most_c_obj *d,
+			 struct most_c_attr *attr,
+			 const char *buf,
+			 size_t count);
+};
+
+#define to_channel_attr(a) container_of(a, struct most_c_attr, attr)
+
+/**
+ * channel_attr_show - show function of channel object
+ * @kobj: pointer to its kobject
+ * @attr: pointer to its attributes
+ * @buf: buffer
+ */
+static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr,
+				 char *buf)
+{
+	struct most_c_attr *channel_attr = to_channel_attr(attr);
+	struct most_c_obj *c_obj = to_c_obj(kobj);
+
+	if (!channel_attr->show)
+		return -EIO;
+
+	return channel_attr->show(c_obj, channel_attr, buf);
+}
+
+/**
+ * channel_attr_store - store function of channel object
+ * @kobj: pointer to its kobject
+ * @attr: pointer to its attributes
+ * @buf: buffer
+ * @len: length of buffer
+ */
+static ssize_t channel_attr_store(struct kobject *kobj,
+				  struct attribute *attr,
+				  const char *buf,
+				  size_t len)
+{
+	struct most_c_attr *channel_attr = to_channel_attr(attr);
+	struct most_c_obj *c_obj = to_c_obj(kobj);
+
+	if (!channel_attr->store)
+		return -EIO;
+	return channel_attr->store(c_obj, channel_attr, buf, len);
+}
+
+static const struct sysfs_ops most_channel_sysfs_ops = {
+	.show = channel_attr_show,
+	.store = channel_attr_store,
+};
+
+/**
+ * most_free_mbo_coherent - free an MBO and its coherent buffer
+ * @mbo: buffer to be released
+ *
+ */
+static void most_free_mbo_coherent(struct mbo *mbo)
+{
+	struct most_c_obj *c = mbo->context;
+	u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
+
+	dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address,
+			  mbo->bus_address);
+	kfree(mbo);
+	if (atomic_sub_and_test(1, &c->mbo_ref))
+		complete(&c->cleanup);
+}
+
+/**
+ * flush_channel_fifos - clear the channel fifos
+ * @c: pointer to channel object
+ */
+static void flush_channel_fifos(struct most_c_obj *c)
+{
+	unsigned long flags, hf_flags;
+	struct mbo *mbo, *tmp;
+
+	if (list_empty(&c->fifo) && list_empty(&c->halt_fifo))
+		return;
+
+	spin_lock_irqsave(&c->fifo_lock, flags);
+	list_for_each_entry_safe(mbo, tmp, &c->fifo, list) {
+		list_del(&mbo->list);
+		spin_unlock_irqrestore(&c->fifo_lock, flags);
+		most_free_mbo_coherent(mbo);
+		spin_lock_irqsave(&c->fifo_lock, flags);
+	}
+	spin_unlock_irqrestore(&c->fifo_lock, flags);
+
+	spin_lock_irqsave(&c->fifo_lock, hf_flags);
+	list_for_each_entry_safe(mbo, tmp, &c->halt_fifo, list) {
+		list_del(&mbo->list);
+		spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
+		most_free_mbo_coherent(mbo);
+		spin_lock_irqsave(&c->fifo_lock, hf_flags);
+	}
+	spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
+
+	if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo))))
+		pr_info("WARN: fifo | trash fifo not empty\n");
+}
+
+/**
+ * flush_trash_fifo - clear the trash fifo
+ * @c: pointer to channel object
+ */
+static int flush_trash_fifo(struct most_c_obj *c)
+{
+	struct mbo *mbo, *tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&c->fifo_lock, flags);
+	list_for_each_entry_safe(mbo, tmp, &c->trash_fifo, list) {
+		list_del(&mbo->list);
+		spin_unlock_irqrestore(&c->fifo_lock, flags);
+		most_free_mbo_coherent(mbo);
+		spin_lock_irqsave(&c->fifo_lock, flags);
+	}
+	spin_unlock_irqrestore(&c->fifo_lock, flags);
+	return 0;
+}
+
+/**
+ * most_channel_release - release function of channel object
+ * @kobj: pointer to channel's kobject
+ */
+static void most_channel_release(struct kobject *kobj)
+{
+	struct most_c_obj *c = to_c_obj(kobj);
+
+	kfree(c);
+}
+
+static ssize_t available_directions_show(struct most_c_obj *c,
+					 struct most_c_attr *attr,
+					 char *buf)
+{
+	unsigned int i = c->channel_id;
+
+	strcpy(buf, "");
+	if (c->iface->channel_vector[i].direction & MOST_CH_RX)
+		strcat(buf, "rx ");
+	if (c->iface->channel_vector[i].direction & MOST_CH_TX)
+		strcat(buf, "tx ");
+	strcat(buf, "\n");
+	return strlen(buf);
+}
+
+static ssize_t available_datatypes_show(struct most_c_obj *c,
+					struct most_c_attr *attr,
+					char *buf)
+{
+	unsigned int i = c->channel_id;
+
+	strcpy(buf, "");
+	if (c->iface->channel_vector[i].data_type & MOST_CH_CONTROL)
+		strcat(buf, "control ");
+	if (c->iface->channel_vector[i].data_type & MOST_CH_ASYNC)
+		strcat(buf, "async ");
+	if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC)
+		strcat(buf, "sync ");
+	if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC)
+		strcat(buf, "isoc ");
+	strcat(buf, "\n");
+	return strlen(buf);
+}
+
+static ssize_t number_of_packet_buffers_show(struct most_c_obj *c,
+					     struct most_c_attr *attr,
+					     char *buf)
+{
+	unsigned int i = c->channel_id;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			c->iface->channel_vector[i].num_buffers_packet);
+}
+
+static ssize_t number_of_stream_buffers_show(struct most_c_obj *c,
+					     struct most_c_attr *attr,
+					     char *buf)
+{
+	unsigned int i = c->channel_id;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			c->iface->channel_vector[i].num_buffers_streaming);
+}
+
+static ssize_t size_of_packet_buffer_show(struct most_c_obj *c,
+					  struct most_c_attr *attr,
+					  char *buf)
+{
+	unsigned int i = c->channel_id;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			c->iface->channel_vector[i].buffer_size_packet);
+}
+
+static ssize_t size_of_stream_buffer_show(struct most_c_obj *c,
+					  struct most_c_attr *attr,
+					  char *buf)
+{
+	unsigned int i = c->channel_id;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			c->iface->channel_vector[i].buffer_size_streaming);
+}
+
+static ssize_t channel_starving_show(struct most_c_obj *c,
+				     struct most_c_attr *attr,
+				     char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving);
+}
+
+static ssize_t set_number_of_buffers_show(struct most_c_obj *c,
+					  struct most_c_attr *attr,
+					  char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers);
+}
+
+static ssize_t set_number_of_buffers_store(struct most_c_obj *c,
+					   struct most_c_attr *attr,
+					   const char *buf,
+					   size_t count)
+{
+	int ret = kstrtou16(buf, 0, &c->cfg.num_buffers);
+
+	if (ret)
+		return ret;
+	return count;
+}
+
+static ssize_t set_buffer_size_show(struct most_c_obj *c,
+				    struct most_c_attr *attr,
+				    char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size);
+}
+
+static ssize_t set_buffer_size_store(struct most_c_obj *c,
+				     struct most_c_attr *attr,
+				     const char *buf,
+				     size_t count)
+{
+	int ret = kstrtou16(buf, 0, &c->cfg.buffer_size);
+
+	if (ret)
+		return ret;
+	return count;
+}
+
+static ssize_t set_direction_show(struct most_c_obj *c,
+				  struct most_c_attr *attr,
+				  char *buf)
+{
+	if (c->cfg.direction & MOST_CH_TX)
+		return snprintf(buf, PAGE_SIZE, "tx\n");
+	else if (c->cfg.direction & MOST_CH_RX)
+		return snprintf(buf, PAGE_SIZE, "rx\n");
+	return snprintf(buf, PAGE_SIZE, "unconfigured\n");
+}
+
+static ssize_t set_direction_store(struct most_c_obj *c,
+				   struct most_c_attr *attr,
+				   const char *buf,
+				   size_t count)
+{
+	if (!strcmp(buf, "dir_rx\n")) {
+		c->cfg.direction = MOST_CH_RX;
+	} else if (!strcmp(buf, "rx\n")) {
+		c->cfg.direction = MOST_CH_RX;
+	} else if (!strcmp(buf, "dir_tx\n")) {
+		c->cfg.direction = MOST_CH_TX;
+	} else if (!strcmp(buf, "tx\n")) {
+		c->cfg.direction = MOST_CH_TX;
+	} else {
+		pr_info("WARN: invalid attribute settings\n");
+		return -EINVAL;
+	}
+	return count;
+}
+
+static ssize_t set_datatype_show(struct most_c_obj *c,
+				 struct most_c_attr *attr,
+				 char *buf)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
+		if (c->cfg.data_type & ch_data_type[i].most_ch_data_type)
+			return snprintf(buf, PAGE_SIZE, ch_data_type[i].name);
+	}
+	return snprintf(buf, PAGE_SIZE, "unconfigured\n");
+}
+
+static ssize_t set_datatype_store(struct most_c_obj *c,
+				  struct most_c_attr *attr,
+				  const char *buf,
+				  size_t count)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
+		if (!strcmp(buf, ch_data_type[i].name)) {
+			c->cfg.data_type = ch_data_type[i].most_ch_data_type;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(ch_data_type)) {
+		pr_info("WARN: invalid attribute settings\n");
+		return -EINVAL;
+	}
+	return count;
+}
+
+static ssize_t set_subbuffer_size_show(struct most_c_obj *c,
+				       struct most_c_attr *attr,
+				       char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size);
+}
+
+static ssize_t set_subbuffer_size_store(struct most_c_obj *c,
+					struct most_c_attr *attr,
+					const char *buf,
+					size_t count)
+{
+	int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size);
+
+	if (ret)
+		return ret;
+	return count;
+}
+
+static ssize_t set_packets_per_xact_show(struct most_c_obj *c,
+					 struct most_c_attr *attr,
+					 char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact);
+}
+
+static ssize_t set_packets_per_xact_store(struct most_c_obj *c,
+					  struct most_c_attr *attr,
+					  const char *buf,
+					  size_t count)
+{
+	int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact);
+
+	if (ret)
+		return ret;
+	return count;
+}
+
+static struct most_c_attr most_c_attrs[] = {
+	__ATTR_RO(available_directions),
+	__ATTR_RO(available_datatypes),
+	__ATTR_RO(number_of_packet_buffers),
+	__ATTR_RO(number_of_stream_buffers),
+	__ATTR_RO(size_of_stream_buffer),
+	__ATTR_RO(size_of_packet_buffer),
+	__ATTR_RO(channel_starving),
+	__ATTR_RW(set_buffer_size),
+	__ATTR_RW(set_number_of_buffers),
+	__ATTR_RW(set_direction),
+	__ATTR_RW(set_datatype),
+	__ATTR_RW(set_subbuffer_size),
+	__ATTR_RW(set_packets_per_xact),
+};
+
+/**
+ * most_channel_def_attrs - array of default attributes of channel object
+ */
+static struct attribute *most_channel_def_attrs[] = {
+	&most_c_attrs[0].attr,
+	&most_c_attrs[1].attr,
+	&most_c_attrs[2].attr,
+	&most_c_attrs[3].attr,
+	&most_c_attrs[4].attr,
+	&most_c_attrs[5].attr,
+	&most_c_attrs[6].attr,
+	&most_c_attrs[7].attr,
+	&most_c_attrs[8].attr,
+	&most_c_attrs[9].attr,
+	&most_c_attrs[10].attr,
+	&most_c_attrs[11].attr,
+	&most_c_attrs[12].attr,
+	NULL,
+};
+
+static struct kobj_type most_channel_ktype = {
+	.sysfs_ops = &most_channel_sysfs_ops,
+	.release = most_channel_release,
+	.default_attrs = most_channel_def_attrs,
+};
+
+static struct kset *most_channel_kset;
+
+/**
+ * create_most_c_obj - allocates a channel object
+ * @name: name of the channel object
+ * @parent: parent kobject
+ *
+ * This create a channel object and registers it with sysfs.
+ * Returns a pointer to the object or NULL when something went wrong.
+ */
+static struct most_c_obj *
+create_most_c_obj(const char *name, struct kobject *parent)
+{
+	struct most_c_obj *c;
+	int retval;
+
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return NULL;
+	c->kobj.kset = most_channel_kset;
+	retval = kobject_init_and_add(&c->kobj, &most_channel_ktype, parent,
+				      "%s", name);
+	if (retval) {
+		kobject_put(&c->kobj);
+		return NULL;
+	}
+	kobject_uevent(&c->kobj, KOBJ_ADD);
+	return c;
+}
+
+/*		     ___	       ___
+ *		     ___I N S T A N C E___
+ */
+
+static struct list_head instance_list;
+
+/**
+ * struct most_inst_attribute - to access the attributes of instance object
+ * @attr: attributes of an instance
+ * @show: pointer to the show function
+ * @store: pointer to the store function
+ */
+struct most_inst_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct most_inst_obj *d,
+			struct most_inst_attribute *attr,
+			char *buf);
+	ssize_t (*store)(struct most_inst_obj *d,
+			 struct most_inst_attribute *attr,
+			 const char *buf,
+			 size_t count);
+};
+
+#define to_instance_attr(a) \
+	container_of(a, struct most_inst_attribute, attr)
+
+/**
+ * instance_attr_show - show function for an instance object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ */
+static ssize_t instance_attr_show(struct kobject *kobj,
+				  struct attribute *attr,
+				  char *buf)
+{
+	struct most_inst_attribute *instance_attr;
+	struct most_inst_obj *instance_obj;
+
+	instance_attr = to_instance_attr(attr);
+	instance_obj = to_inst_obj(kobj);
+
+	if (!instance_attr->show)
+		return -EIO;
+
+	return instance_attr->show(instance_obj, instance_attr, buf);
+}
+
+/**
+ * instance_attr_store - store function for an instance object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ * @len: length of buffer
+ */
+static ssize_t instance_attr_store(struct kobject *kobj,
+				   struct attribute *attr,
+				   const char *buf,
+				   size_t len)
+{
+	struct most_inst_attribute *instance_attr;
+	struct most_inst_obj *instance_obj;
+
+	instance_attr = to_instance_attr(attr);
+	instance_obj = to_inst_obj(kobj);
+
+	if (!instance_attr->store)
+		return -EIO;
+
+	return instance_attr->store(instance_obj, instance_attr, buf, len);
+}
+
+static const struct sysfs_ops most_inst_sysfs_ops = {
+	.show = instance_attr_show,
+	.store = instance_attr_store,
+};
+
+/**
+ * most_inst_release - release function for instance object
+ * @kobj: pointer to instance's kobject
+ *
+ * This frees the allocated memory for the instance object
+ */
+static void most_inst_release(struct kobject *kobj)
+{
+	struct most_inst_obj *inst = to_inst_obj(kobj);
+
+	kfree(inst);
+}
+
+static ssize_t description_show(struct most_inst_obj *instance_obj,
+				struct most_inst_attribute *attr,
+				char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			instance_obj->iface->description);
+}
+
+static ssize_t interface_show(struct most_inst_obj *instance_obj,
+			      struct most_inst_attribute *attr,
+			      char *buf)
+{
+	switch (instance_obj->iface->interface) {
+	case ITYPE_LOOPBACK:
+		return snprintf(buf, PAGE_SIZE, "loopback\n");
+	case ITYPE_I2C:
+		return snprintf(buf, PAGE_SIZE, "i2c\n");
+	case ITYPE_I2S:
+		return snprintf(buf, PAGE_SIZE, "i2s\n");
+	case ITYPE_TSI:
+		return snprintf(buf, PAGE_SIZE, "tsi\n");
+	case ITYPE_HBI:
+		return snprintf(buf, PAGE_SIZE, "hbi\n");
+	case ITYPE_MEDIALB_DIM:
+		return snprintf(buf, PAGE_SIZE, "mlb_dim\n");
+	case ITYPE_MEDIALB_DIM2:
+		return snprintf(buf, PAGE_SIZE, "mlb_dim2\n");
+	case ITYPE_USB:
+		return snprintf(buf, PAGE_SIZE, "usb\n");
+	case ITYPE_PCIE:
+		return snprintf(buf, PAGE_SIZE, "pcie\n");
+	}
+	return snprintf(buf, PAGE_SIZE, "unknown\n");
+}
+
+static struct most_inst_attribute most_inst_attr_description =
+	__ATTR_RO(description);
+
+static struct most_inst_attribute most_inst_attr_interface =
+	__ATTR_RO(interface);
+
+static struct attribute *most_inst_def_attrs[] = {
+	&most_inst_attr_description.attr,
+	&most_inst_attr_interface.attr,
+	NULL,
+};
+
+static struct kobj_type most_inst_ktype = {
+	.sysfs_ops = &most_inst_sysfs_ops,
+	.release = most_inst_release,
+	.default_attrs = most_inst_def_attrs,
+};
+
+static struct kset *most_inst_kset;
+
+/**
+ * create_most_inst_obj - creates an instance object
+ * @name: name of the object to be created
+ *
+ * This allocates memory for an instance structure, assigns the proper kset
+ * and registers it with sysfs.
+ *
+ * Returns a pointer to the instance object or NULL when something went wrong.
+ */
+static struct most_inst_obj *create_most_inst_obj(const char *name)
+{
+	struct most_inst_obj *inst;
+	int retval;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return NULL;
+	inst->kobj.kset = most_inst_kset;
+	retval = kobject_init_and_add(&inst->kobj, &most_inst_ktype, NULL,
+				      "%s", name);
+	if (retval) {
+		kobject_put(&inst->kobj);
+		return NULL;
+	}
+	kobject_uevent(&inst->kobj, KOBJ_ADD);
+	return inst;
+}
+
+/**
+ * destroy_most_inst_obj - MOST instance release function
+ * @inst: pointer to the instance object
+ *
+ * This decrements the reference counter of the instance object.
+ * If the reference count turns zero, its release function is called
+ */
+static void destroy_most_inst_obj(struct most_inst_obj *inst)
+{
+	struct most_c_obj *c, *tmp;
+
+	list_for_each_entry_safe(c, tmp, &inst->channel_list, list) {
+		flush_trash_fifo(c);
+		flush_channel_fifos(c);
+		kobject_put(&c->kobj);
+	}
+	kobject_put(&inst->kobj);
+}
+
+/*		     ___     ___
+ *		     ___A I M___
+ */
+struct most_aim_obj {
+	struct kobject kobj;
+	struct list_head list;
+	struct most_aim *driver;
+};
+
+#define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj)
+
+static struct list_head aim_list;
+
+/**
+ * struct most_aim_attribute - to access the attributes of AIM object
+ * @attr: attributes of an AIM
+ * @show: pointer to the show function
+ * @store: pointer to the store function
+ */
+struct most_aim_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct most_aim_obj *d,
+			struct most_aim_attribute *attr,
+			char *buf);
+	ssize_t (*store)(struct most_aim_obj *d,
+			 struct most_aim_attribute *attr,
+			 const char *buf,
+			 size_t count);
+};
+
+#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr)
+
+/**
+ * aim_attr_show - show function of an AIM object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ */
+static ssize_t aim_attr_show(struct kobject *kobj,
+			     struct attribute *attr,
+			     char *buf)
+{
+	struct most_aim_attribute *aim_attr;
+	struct most_aim_obj *aim_obj;
+
+	aim_attr = to_aim_attr(attr);
+	aim_obj = to_aim_obj(kobj);
+
+	if (!aim_attr->show)
+		return -EIO;
+
+	return aim_attr->show(aim_obj, aim_attr, buf);
+}
+
+/**
+ * aim_attr_store - store function of an AIM object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ * @len: length of buffer
+ */
+static ssize_t aim_attr_store(struct kobject *kobj,
+			      struct attribute *attr,
+			      const char *buf,
+			      size_t len)
+{
+	struct most_aim_attribute *aim_attr;
+	struct most_aim_obj *aim_obj;
+
+	aim_attr = to_aim_attr(attr);
+	aim_obj = to_aim_obj(kobj);
+
+	if (!aim_attr->store)
+		return -EIO;
+	return aim_attr->store(aim_obj, aim_attr, buf, len);
+}
+
+static const struct sysfs_ops most_aim_sysfs_ops = {
+	.show = aim_attr_show,
+	.store = aim_attr_store,
+};
+
+/**
+ * most_aim_release - AIM release function
+ * @kobj: pointer to AIM's kobject
+ */
+static void most_aim_release(struct kobject *kobj)
+{
+	struct most_aim_obj *aim_obj = to_aim_obj(kobj);
+
+	kfree(aim_obj);
+}
+
+static ssize_t links_show(struct most_aim_obj *aim_obj,
+			  struct most_aim_attribute *attr,
+			  char *buf)
+{
+	struct most_c_obj *c;
+	struct most_inst_obj *i;
+	int offs = 0;
+
+	list_for_each_entry(i, &instance_list, list) {
+		list_for_each_entry(c, &i->channel_list, list) {
+			if (c->aim0.ptr == aim_obj->driver ||
+			    c->aim1.ptr == aim_obj->driver) {
+				offs += snprintf(buf + offs, PAGE_SIZE - offs,
+						 "%s:%s\n",
+						 kobject_name(&i->kobj),
+						 kobject_name(&c->kobj));
+			}
+		}
+	}
+
+	return offs;
+}
+
+/**
+ * split_string - parses and changes string in the buffer buf and
+ * splits it into two mandatory and one optional substrings.
+ *
+ * @buf: complete string from attribute 'add_channel'
+ * @a: address of pointer to 1st substring (=instance name)
+ * @b: address of pointer to 2nd substring (=channel name)
+ * @c: optional address of pointer to 3rd substring (=user defined name)
+ *
+ * Examples:
+ *
+ * Input: "mdev0:ch6:my_channel\n" or
+ *        "mdev0:ch6:my_channel"
+ *
+ * Output: *a -> "mdev0", *b -> "ch6", *c -> "my_channel"
+ *
+ * Input: "mdev1:ep81\n"
+ * Output: *a -> "mdev1", *b -> "ep81", *c -> ""
+ *
+ * Input: "mdev1:ep81"
+ * Output: *a -> "mdev1", *b -> "ep81", *c == NULL
+ */
+static int split_string(char *buf, char **a, char **b, char **c)
+{
+	*a = strsep(&buf, ":");
+	if (!*a)
+		return -EIO;
+
+	*b = strsep(&buf, ":\n");
+	if (!*b)
+		return -EIO;
+
+	if (c)
+		*c = strsep(&buf, ":\n");
+
+	return 0;
+}
+
+/**
+ * get_channel_by_name - get pointer to channel object
+ * @mdev: name of the device instance
+ * @mdev_ch: name of the respective channel
+ *
+ * This retrieves the pointer to a channel object.
+ */
+static struct
+most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
+{
+	struct most_c_obj *c, *tmp;
+	struct most_inst_obj *i, *i_tmp;
+	int found = 0;
+
+	list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
+		if (!strcmp(kobject_name(&i->kobj), mdev)) {
+			found++;
+			break;
+		}
+	}
+	if (unlikely(!found))
+		return ERR_PTR(-EIO);
+
+	list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
+		if (!strcmp(kobject_name(&c->kobj), mdev_ch)) {
+			found++;
+			break;
+		}
+	}
+	if (unlikely(found < 2))
+		return ERR_PTR(-EIO);
+	return c;
+}
+
+/**
+ * add_link_store - store() function for add_link attribute
+ * @aim_obj: pointer to AIM object
+ * @attr: its attributes
+ * @buf: buffer
+ * @len: buffer length
+ *
+ * This parses the string given by buf and splits it into
+ * three substrings. Note: third substring is optional. In case a cdev
+ * AIM is loaded the optional 3rd substring will make up the name of
+ * device node in the /dev directory. If omitted, the device node will
+ * inherit the channel's name within sysfs.
+ *
+ * Searches for a pair of device and channel and probes the AIM
+ *
+ * Example:
+ * (1) echo "mdev0:ch6:my_rxchannel" >add_link
+ * (2) echo "mdev1:ep81" >add_link
+ *
+ * (1) would create the device node /dev/my_rxchannel
+ * (2) would create the device node /dev/mdev1-ep81
+ */
+static ssize_t add_link_store(struct most_aim_obj *aim_obj,
+			      struct most_aim_attribute *attr,
+			      const char *buf,
+			      size_t len)
+{
+	struct most_c_obj *c;
+	struct most_aim **aim_ptr;
+	char buffer[STRING_SIZE];
+	char *mdev;
+	char *mdev_ch;
+	char *mdev_devnod;
+	char devnod_buf[STRING_SIZE];
+	int ret;
+	size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
+
+	strlcpy(buffer, buf, max_len);
+
+	ret = split_string(buffer, &mdev, &mdev_ch, &mdev_devnod);
+	if (ret)
+		return ret;
+
+	if (!mdev_devnod || *mdev_devnod == 0) {
+		snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev,
+			 mdev_ch);
+		mdev_devnod = devnod_buf;
+	}
+
+	c = get_channel_by_name(mdev, mdev_ch);
+	if (IS_ERR(c))
+		return -ENODEV;
+
+	if (!c->aim0.ptr)
+		aim_ptr = &c->aim0.ptr;
+	else if (!c->aim1.ptr)
+		aim_ptr = &c->aim1.ptr;
+	else
+		return -ENOSPC;
+
+	*aim_ptr = aim_obj->driver;
+	ret = aim_obj->driver->probe_channel(c->iface, c->channel_id,
+					     &c->cfg, &c->kobj, mdev_devnod);
+	if (ret) {
+		*aim_ptr = NULL;
+		return ret;
+	}
+
+	return len;
+}
+
+/**
+ * remove_link_store - store function for remove_link attribute
+ * @aim_obj: pointer to AIM object
+ * @attr: its attributes
+ * @buf: buffer
+ * @len: buffer length
+ *
+ * Example:
+ * echo "mdev0:ep81" >remove_link
+ */
+static ssize_t remove_link_store(struct most_aim_obj *aim_obj,
+				 struct most_aim_attribute *attr,
+				 const char *buf,
+				 size_t len)
+{
+	struct most_c_obj *c;
+	char buffer[STRING_SIZE];
+	char *mdev;
+	char *mdev_ch;
+	int ret;
+	size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
+
+	strlcpy(buffer, buf, max_len);
+	ret = split_string(buffer, &mdev, &mdev_ch, NULL);
+	if (ret)
+		return ret;
+
+	c = get_channel_by_name(mdev, mdev_ch);
+	if (IS_ERR(c))
+		return -ENODEV;
+
+	if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id))
+		return -EIO;
+	if (c->aim0.ptr == aim_obj->driver)
+		c->aim0.ptr = NULL;
+	if (c->aim1.ptr == aim_obj->driver)
+		c->aim1.ptr = NULL;
+	return len;
+}
+
+static struct most_aim_attribute most_aim_attrs[] = {
+	__ATTR_RO(links),
+	__ATTR_WO(add_link),
+	__ATTR_WO(remove_link),
+};
+
+static struct attribute *most_aim_def_attrs[] = {
+	&most_aim_attrs[0].attr,
+	&most_aim_attrs[1].attr,
+	&most_aim_attrs[2].attr,
+	NULL,
+};
+
+static struct kobj_type most_aim_ktype = {
+	.sysfs_ops = &most_aim_sysfs_ops,
+	.release = most_aim_release,
+	.default_attrs = most_aim_def_attrs,
+};
+
+static struct kset *most_aim_kset;
+
+/**
+ * create_most_aim_obj - creates an AIM object
+ * @name: name of the AIM
+ *
+ * This creates an AIM object assigns the proper kset and registers
+ * it with sysfs.
+ * Returns a pointer to the object or NULL if something went wrong.
+ */
+static struct most_aim_obj *create_most_aim_obj(const char *name)
+{
+	struct most_aim_obj *most_aim;
+	int retval;
+
+	most_aim = kzalloc(sizeof(*most_aim), GFP_KERNEL);
+	if (!most_aim)
+		return NULL;
+	most_aim->kobj.kset = most_aim_kset;
+	retval = kobject_init_and_add(&most_aim->kobj, &most_aim_ktype,
+				      NULL, "%s", name);
+	if (retval) {
+		kobject_put(&most_aim->kobj);
+		return NULL;
+	}
+	kobject_uevent(&most_aim->kobj, KOBJ_ADD);
+	return most_aim;
+}
+
+/**
+ * destroy_most_aim_obj - AIM release function
+ * @p: pointer to AIM object
+ *
+ * This decrements the reference counter of the AIM object. If the
+ * reference count turns zero, its release function will be called.
+ */
+static void destroy_most_aim_obj(struct most_aim_obj *p)
+{
+	kobject_put(&p->kobj);
+}
+
+/*		     ___       ___
+ *		     ___C O R E___
+ */
+
+/**
+ * Instantiation of the MOST bus
+ */
+static struct bus_type most_bus = {
+	.name = "most",
+};
+
+/**
+ * Instantiation of the core driver
+ */
+static struct device_driver mostcore = {
+	.name = "mostcore",
+	.bus = &most_bus,
+};
+
+static inline void trash_mbo(struct mbo *mbo)
+{
+	unsigned long flags;
+	struct most_c_obj *c = mbo->context;
+
+	spin_lock_irqsave(&c->fifo_lock, flags);
+	list_add(&mbo->list, &c->trash_fifo);
+	spin_unlock_irqrestore(&c->fifo_lock, flags);
+}
+
+static bool hdm_mbo_ready(struct most_c_obj *c)
+{
+	bool empty;
+
+	if (c->enqueue_halt)
+		return false;
+
+	spin_lock_irq(&c->fifo_lock);
+	empty = list_empty(&c->halt_fifo);
+	spin_unlock_irq(&c->fifo_lock);
+
+	return !empty;
+}
+
+static void nq_hdm_mbo(struct mbo *mbo)
+{
+	unsigned long flags;
+	struct most_c_obj *c = mbo->context;
+
+	spin_lock_irqsave(&c->fifo_lock, flags);
+	list_add_tail(&mbo->list, &c->halt_fifo);
+	spin_unlock_irqrestore(&c->fifo_lock, flags);
+	wake_up_interruptible(&c->hdm_fifo_wq);
+}
+
+static int hdm_enqueue_thread(void *data)
+{
+	struct most_c_obj *c = data;
+	struct mbo *mbo;
+	int ret;
+	typeof(c->iface->enqueue) enqueue = c->iface->enqueue;
+
+	while (likely(!kthread_should_stop())) {
+		wait_event_interruptible(c->hdm_fifo_wq,
+					 hdm_mbo_ready(c) ||
+					 kthread_should_stop());
+
+		mutex_lock(&c->nq_mutex);
+		spin_lock_irq(&c->fifo_lock);
+		if (unlikely(c->enqueue_halt || list_empty(&c->halt_fifo))) {
+			spin_unlock_irq(&c->fifo_lock);
+			mutex_unlock(&c->nq_mutex);
+			continue;
+		}
+
+		mbo = list_pop_mbo(&c->halt_fifo);
+		spin_unlock_irq(&c->fifo_lock);
+
+		if (c->cfg.direction == MOST_CH_RX)
+			mbo->buffer_length = c->cfg.buffer_size;
+
+		ret = enqueue(mbo->ifp, mbo->hdm_channel_id, mbo);
+		mutex_unlock(&c->nq_mutex);
+
+		if (unlikely(ret)) {
+			pr_err("hdm enqueue failed\n");
+			nq_hdm_mbo(mbo);
+			c->hdm_enqueue_task = NULL;
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static int run_enqueue_thread(struct most_c_obj *c, int channel_id)
+{
+	struct task_struct *task =
+		kthread_run(hdm_enqueue_thread, c, "hdm_fifo_%d",
+			    channel_id);
+
+	if (IS_ERR(task))
+		return PTR_ERR(task);
+
+	c->hdm_enqueue_task = task;
+	return 0;
+}
+
+/**
+ * arm_mbo - recycle MBO for further usage
+ * @mbo: buffer object
+ *
+ * This puts an MBO back to the list to have it ready for up coming
+ * tx transactions.
+ *
+ * In case the MBO belongs to a channel that recently has been
+ * poisoned, the MBO is scheduled to be trashed.
+ * Calls the completion handler of an attached AIM.
+ */
+static void arm_mbo(struct mbo *mbo)
+{
+	unsigned long flags;
+	struct most_c_obj *c;
+
+	BUG_ON((!mbo) || (!mbo->context));
+	c = mbo->context;
+
+	if (c->is_poisoned) {
+		trash_mbo(mbo);
+		return;
+	}
+
+	spin_lock_irqsave(&c->fifo_lock, flags);
+	++*mbo->num_buffers_ptr;
+	list_add_tail(&mbo->list, &c->fifo);
+	spin_unlock_irqrestore(&c->fifo_lock, flags);
+
+	if (c->aim0.refs && c->aim0.ptr->tx_completion)
+		c->aim0.ptr->tx_completion(c->iface, c->channel_id);
+
+	if (c->aim1.refs && c->aim1.ptr->tx_completion)
+		c->aim1.ptr->tx_completion(c->iface, c->channel_id);
+}
+
+/**
+ * arm_mbo_chain - helper function that arms an MBO chain for the HDM
+ * @c: pointer to interface channel
+ * @dir: direction of the channel
+ * @compl: pointer to completion function
+ *
+ * This allocates buffer objects including the containing DMA coherent
+ * buffer and puts them in the fifo.
+ * Buffers of Rx channels are put in the kthread fifo, hence immediately
+ * submitted to the HDM.
+ *
+ * Returns the number of allocated and enqueued MBOs.
+ */
+static int arm_mbo_chain(struct most_c_obj *c, int dir,
+			 void (*compl)(struct mbo *))
+{
+	unsigned int i;
+	int retval;
+	struct mbo *mbo;
+	u32 coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
+
+	atomic_set(&c->mbo_nq_level, 0);
+
+	for (i = 0; i < c->cfg.num_buffers; i++) {
+		mbo = kzalloc(sizeof(*mbo), GFP_KERNEL);
+		if (!mbo) {
+			retval = i;
+			goto _exit;
+		}
+		mbo->context = c;
+		mbo->ifp = c->iface;
+		mbo->hdm_channel_id = c->channel_id;
+		mbo->virt_address = dma_alloc_coherent(NULL,
+						       coherent_buf_size,
+						       &mbo->bus_address,
+						       GFP_KERNEL);
+		if (!mbo->virt_address) {
+			pr_info("WARN: No DMA coherent buffer.\n");
+			retval = i;
+			goto _error1;
+		}
+		mbo->complete = compl;
+		mbo->num_buffers_ptr = &dummy_num_buffers;
+		if (dir == MOST_CH_RX) {
+			nq_hdm_mbo(mbo);
+			atomic_inc(&c->mbo_nq_level);
+		} else {
+			arm_mbo(mbo);
+		}
+	}
+	return i;
+
+_error1:
+	kfree(mbo);
+_exit:
+	return retval;
+}
+
+/**
+ * most_submit_mbo - submits an MBO to fifo
+ * @mbo: pointer to the MBO
+ */
+void most_submit_mbo(struct mbo *mbo)
+{
+	if (WARN_ONCE(!mbo || !mbo->context,
+		      "bad mbo or missing channel reference\n"))
+		return;
+
+	nq_hdm_mbo(mbo);
+}
+EXPORT_SYMBOL_GPL(most_submit_mbo);
+
+/**
+ * most_write_completion - write completion handler
+ * @mbo: pointer to MBO
+ *
+ * This recycles the MBO for further usage. In case the channel has been
+ * poisoned, the MBO is scheduled to be trashed.
+ */
+static void most_write_completion(struct mbo *mbo)
+{
+	struct most_c_obj *c;
+
+	BUG_ON((!mbo) || (!mbo->context));
+
+	c = mbo->context;
+	if (mbo->status == MBO_E_INVAL)
+		pr_info("WARN: Tx MBO status: invalid\n");
+	if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE)))
+		trash_mbo(mbo);
+	else
+		arm_mbo(mbo);
+}
+
+/**
+ * get_channel_by_iface - get pointer to channel object
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ *
+ * This retrieves a pointer to a channel of the given interface and channel ID.
+ */
+static struct
+most_c_obj *get_channel_by_iface(struct most_interface *iface, int id)
+{
+	struct most_inst_obj *i;
+
+	if (unlikely(!iface)) {
+		pr_err("Bad interface\n");
+		return NULL;
+	}
+	if (unlikely((id < 0) || (id >= iface->num_channels))) {
+		pr_err("Channel index (%d) out of range\n", id);
+		return NULL;
+	}
+	i = iface->priv;
+	if (unlikely(!i)) {
+		pr_err("interface is not registered\n");
+		return NULL;
+	}
+	return i->channel[id];
+}
+
+int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim)
+{
+	struct most_c_obj *c = get_channel_by_iface(iface, id);
+	unsigned long flags;
+	int empty;
+
+	if (unlikely(!c))
+		return -EINVAL;
+
+	if (c->aim0.refs && c->aim1.refs &&
+	    ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) ||
+	     (aim == c->aim1.ptr && c->aim1.num_buffers <= 0)))
+		return 0;
+
+	spin_lock_irqsave(&c->fifo_lock, flags);
+	empty = list_empty(&c->fifo);
+	spin_unlock_irqrestore(&c->fifo_lock, flags);
+	return !empty;
+}
+EXPORT_SYMBOL_GPL(channel_has_mbo);
+
+/**
+ * most_get_mbo - get pointer to an MBO of pool
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ *
+ * This attempts to get a free buffer out of the channel fifo.
+ * Returns a pointer to MBO on success or NULL otherwise.
+ */
+struct mbo *most_get_mbo(struct most_interface *iface, int id,
+			 struct most_aim *aim)
+{
+	struct mbo *mbo;
+	struct most_c_obj *c;
+	unsigned long flags;
+	int *num_buffers_ptr;
+
+	c = get_channel_by_iface(iface, id);
+	if (unlikely(!c))
+		return NULL;
+
+	if (c->aim0.refs && c->aim1.refs &&
+	    ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) ||
+	     (aim == c->aim1.ptr && c->aim1.num_buffers <= 0)))
+		return NULL;
+
+	if (aim == c->aim0.ptr)
+		num_buffers_ptr = &c->aim0.num_buffers;
+	else if (aim == c->aim1.ptr)
+		num_buffers_ptr = &c->aim1.num_buffers;
+	else
+		num_buffers_ptr = &dummy_num_buffers;
+
+	spin_lock_irqsave(&c->fifo_lock, flags);
+	if (list_empty(&c->fifo)) {
+		spin_unlock_irqrestore(&c->fifo_lock, flags);
+		return NULL;
+	}
+	mbo = list_pop_mbo(&c->fifo);
+	--*num_buffers_ptr;
+	spin_unlock_irqrestore(&c->fifo_lock, flags);
+
+	mbo->num_buffers_ptr = num_buffers_ptr;
+	mbo->buffer_length = c->cfg.buffer_size;
+	return mbo;
+}
+EXPORT_SYMBOL_GPL(most_get_mbo);
+
+/**
+ * most_put_mbo - return buffer to pool
+ * @mbo: buffer object
+ */
+void most_put_mbo(struct mbo *mbo)
+{
+	struct most_c_obj *c = mbo->context;
+
+	if (c->cfg.direction == MOST_CH_TX) {
+		arm_mbo(mbo);
+		return;
+	}
+	nq_hdm_mbo(mbo);
+	atomic_inc(&c->mbo_nq_level);
+}
+EXPORT_SYMBOL_GPL(most_put_mbo);
+
+/**
+ * most_read_completion - read completion handler
+ * @mbo: pointer to MBO
+ *
+ * This function is called by the HDM when data has been received from the
+ * hardware and copied to the buffer of the MBO.
+ *
+ * In case the channel has been poisoned it puts the buffer in the trash queue.
+ * Otherwise, it passes the buffer to an AIM for further processing.
+ */
+static void most_read_completion(struct mbo *mbo)
+{
+	struct most_c_obj *c = mbo->context;
+
+	if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) {
+		trash_mbo(mbo);
+		return;
+	}
+
+	if (mbo->status == MBO_E_INVAL) {
+		nq_hdm_mbo(mbo);
+		atomic_inc(&c->mbo_nq_level);
+		return;
+	}
+
+	if (atomic_sub_and_test(1, &c->mbo_nq_level))
+		c->is_starving = 1;
+
+	if (c->aim0.refs && c->aim0.ptr->rx_completion &&
+	    c->aim0.ptr->rx_completion(mbo) == 0)
+		return;
+
+	if (c->aim1.refs && c->aim1.ptr->rx_completion &&
+	    c->aim1.ptr->rx_completion(mbo) == 0)
+		return;
+
+	most_put_mbo(mbo);
+}
+
+/**
+ * most_start_channel - prepares a channel for communication
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ *
+ * This prepares the channel for usage. Cross-checks whether the
+ * channel's been properly configured.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+int most_start_channel(struct most_interface *iface, int id,
+		       struct most_aim *aim)
+{
+	int num_buffer;
+	int ret;
+	struct most_c_obj *c = get_channel_by_iface(iface, id);
+
+	if (unlikely(!c))
+		return -EINVAL;
+
+	mutex_lock(&c->start_mutex);
+	if (c->aim0.refs + c->aim1.refs > 0)
+		goto out; /* already started by other aim */
+
+	if (!try_module_get(iface->mod)) {
+		pr_info("failed to acquire HDM lock\n");
+		mutex_unlock(&c->start_mutex);
+		return -ENOLCK;
+	}
+
+	c->cfg.extra_len = 0;
+	if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) {
+		pr_info("channel configuration failed. Go check settings...\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	init_waitqueue_head(&c->hdm_fifo_wq);
+
+	if (c->cfg.direction == MOST_CH_RX)
+		num_buffer = arm_mbo_chain(c, c->cfg.direction,
+					   most_read_completion);
+	else
+		num_buffer = arm_mbo_chain(c, c->cfg.direction,
+					   most_write_completion);
+	if (unlikely(!num_buffer)) {
+		pr_info("failed to allocate memory\n");
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	ret = run_enqueue_thread(c, id);
+	if (ret)
+		goto error;
+
+	c->is_starving = 0;
+	c->aim0.num_buffers = c->cfg.num_buffers / 2;
+	c->aim1.num_buffers = c->cfg.num_buffers - c->aim0.num_buffers;
+	atomic_set(&c->mbo_ref, num_buffer);
+
+out:
+	if (aim == c->aim0.ptr)
+		c->aim0.refs++;
+	if (aim == c->aim1.ptr)
+		c->aim1.refs++;
+	mutex_unlock(&c->start_mutex);
+	return 0;
+
+error:
+	module_put(iface->mod);
+	mutex_unlock(&c->start_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(most_start_channel);
+
+/**
+ * most_stop_channel - stops a running channel
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ */
+int most_stop_channel(struct most_interface *iface, int id,
+		      struct most_aim *aim)
+{
+	struct most_c_obj *c;
+
+	if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) {
+		pr_err("Bad interface or index out of range\n");
+		return -EINVAL;
+	}
+	c = get_channel_by_iface(iface, id);
+	if (unlikely(!c))
+		return -EINVAL;
+
+	mutex_lock(&c->start_mutex);
+	if (c->aim0.refs + c->aim1.refs >= 2)
+		goto out;
+
+	if (c->hdm_enqueue_task)
+		kthread_stop(c->hdm_enqueue_task);
+	c->hdm_enqueue_task = NULL;
+
+	if (iface->mod)
+		module_put(iface->mod);
+
+	c->is_poisoned = true;
+	if (c->iface->poison_channel(c->iface, c->channel_id)) {
+		pr_err("Cannot stop channel %d of mdev %s\n", c->channel_id,
+		       c->iface->description);
+		mutex_unlock(&c->start_mutex);
+		return -EAGAIN;
+	}
+	flush_trash_fifo(c);
+	flush_channel_fifos(c);
+
+#ifdef CMPL_INTERRUPTIBLE
+	if (wait_for_completion_interruptible(&c->cleanup)) {
+		pr_info("Interrupted while clean up ch %d\n", c->channel_id);
+		mutex_unlock(&c->start_mutex);
+		return -EINTR;
+	}
+#else
+	wait_for_completion(&c->cleanup);
+#endif
+	c->is_poisoned = false;
+
+out:
+	if (aim == c->aim0.ptr)
+		c->aim0.refs--;
+	if (aim == c->aim1.ptr)
+		c->aim1.refs--;
+	mutex_unlock(&c->start_mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(most_stop_channel);
+
+/**
+ * most_register_aim - registers an AIM (driver) with the core
+ * @aim: instance of AIM to be registered
+ */
+int most_register_aim(struct most_aim *aim)
+{
+	struct most_aim_obj *aim_obj;
+
+	if (!aim) {
+		pr_err("Bad driver\n");
+		return -EINVAL;
+	}
+	aim_obj = create_most_aim_obj(aim->name);
+	if (!aim_obj) {
+		pr_info("failed to alloc driver object\n");
+		return -ENOMEM;
+	}
+	aim_obj->driver = aim;
+	aim->context = aim_obj;
+	pr_info("registered new application interfacing module %s\n",
+		aim->name);
+	list_add_tail(&aim_obj->list, &aim_list);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(most_register_aim);
+
+/**
+ * most_deregister_aim - deregisters an AIM (driver) with the core
+ * @aim: AIM to be removed
+ */
+int most_deregister_aim(struct most_aim *aim)
+{
+	struct most_aim_obj *aim_obj;
+	struct most_c_obj *c, *tmp;
+	struct most_inst_obj *i, *i_tmp;
+
+	if (!aim) {
+		pr_err("Bad driver\n");
+		return -EINVAL;
+	}
+
+	aim_obj = aim->context;
+	if (!aim_obj) {
+		pr_info("driver not registered.\n");
+		return -EINVAL;
+	}
+	list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
+		list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
+			if (c->aim0.ptr == aim || c->aim1.ptr == aim)
+				aim->disconnect_channel(
+					c->iface, c->channel_id);
+			if (c->aim0.ptr == aim)
+				c->aim0.ptr = NULL;
+			if (c->aim1.ptr == aim)
+				c->aim1.ptr = NULL;
+		}
+	}
+	list_del(&aim_obj->list);
+	destroy_most_aim_obj(aim_obj);
+	pr_info("deregistering application interfacing module %s\n", aim->name);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(most_deregister_aim);
+
+/**
+ * most_register_interface - registers an interface with core
+ * @iface: pointer to the instance of the interface description.
+ *
+ * Allocates and initializes a new interface instance and all of its channels.
+ * Returns a pointer to kobject or an error pointer.
+ */
+struct kobject *most_register_interface(struct most_interface *iface)
+{
+	unsigned int i;
+	int id;
+	char name[STRING_SIZE];
+	char channel_name[STRING_SIZE];
+	struct most_c_obj *c;
+	struct most_inst_obj *inst;
+
+	if (!iface || !iface->enqueue || !iface->configure ||
+	    !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) {
+		pr_err("Bad interface or channel overflow\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL);
+	if (id < 0) {
+		pr_info("Failed to alloc mdev ID\n");
+		return ERR_PTR(id);
+	}
+	snprintf(name, STRING_SIZE, "mdev%d", id);
+
+	inst = create_most_inst_obj(name);
+	if (!inst) {
+		pr_info("Failed to allocate interface instance\n");
+		ida_simple_remove(&mdev_id, id);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	iface->priv = inst;
+	INIT_LIST_HEAD(&inst->channel_list);
+	inst->iface = iface;
+	inst->dev_id = id;
+	list_add_tail(&inst->list, &instance_list);
+
+	for (i = 0; i < iface->num_channels; i++) {
+		const char *name_suffix = iface->channel_vector[i].name_suffix;
+
+		if (!name_suffix)
+			snprintf(channel_name, STRING_SIZE, "ch%d", i);
+		else
+			snprintf(channel_name, STRING_SIZE, "%s", name_suffix);
+
+		/* this increments the reference count of this instance */
+		c = create_most_c_obj(channel_name, &inst->kobj);
+		if (!c)
+			goto free_instance;
+		inst->channel[i] = c;
+		c->is_starving = 0;
+		c->iface = iface;
+		c->inst = inst;
+		c->channel_id = i;
+		c->keep_mbo = false;
+		c->enqueue_halt = false;
+		c->is_poisoned = false;
+		c->cfg.direction = 0;
+		c->cfg.data_type = 0;
+		c->cfg.num_buffers = 0;
+		c->cfg.buffer_size = 0;
+		c->cfg.subbuffer_size = 0;
+		c->cfg.packets_per_xact = 0;
+		spin_lock_init(&c->fifo_lock);
+		INIT_LIST_HEAD(&c->fifo);
+		INIT_LIST_HEAD(&c->trash_fifo);
+		INIT_LIST_HEAD(&c->halt_fifo);
+		init_completion(&c->cleanup);
+		atomic_set(&c->mbo_ref, 0);
+		mutex_init(&c->start_mutex);
+		mutex_init(&c->nq_mutex);
+		list_add_tail(&c->list, &inst->channel_list);
+	}
+	pr_info("registered new MOST device mdev%d (%s)\n",
+		inst->dev_id, iface->description);
+	return &inst->kobj;
+
+free_instance:
+	pr_info("Failed allocate channel(s)\n");
+	list_del(&inst->list);
+	ida_simple_remove(&mdev_id, id);
+	destroy_most_inst_obj(inst);
+	return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL_GPL(most_register_interface);
+
+/**
+ * most_deregister_interface - deregisters an interface with core
+ * @iface: pointer to the interface instance description.
+ *
+ * Before removing an interface instance from the list, all running
+ * channels are stopped and poisoned.
+ */
+void most_deregister_interface(struct most_interface *iface)
+{
+	struct most_inst_obj *i = iface->priv;
+	struct most_c_obj *c;
+
+	if (unlikely(!i)) {
+		pr_info("Bad Interface\n");
+		return;
+	}
+	pr_info("deregistering MOST device %s (%s)\n", i->kobj.name,
+		iface->description);
+
+	list_for_each_entry(c, &i->channel_list, list) {
+		if (c->aim0.ptr)
+			c->aim0.ptr->disconnect_channel(c->iface,
+							c->channel_id);
+		if (c->aim1.ptr)
+			c->aim1.ptr->disconnect_channel(c->iface,
+							c->channel_id);
+		c->aim0.ptr = NULL;
+		c->aim1.ptr = NULL;
+	}
+
+	ida_simple_remove(&mdev_id, i->dev_id);
+	list_del(&i->list);
+	destroy_most_inst_obj(i);
+}
+EXPORT_SYMBOL_GPL(most_deregister_interface);
+
+/**
+ * most_stop_enqueue - prevents core from enqueueing MBOs
+ * @iface: pointer to interface
+ * @id: channel id
+ *
+ * This is called by an HDM that _cannot_ attend to its duties and
+ * is imminent to get run over by the core. The core is not going to
+ * enqueue any further packets unless the flagging HDM calls
+ * most_resume enqueue().
+ */
+void most_stop_enqueue(struct most_interface *iface, int id)
+{
+	struct most_c_obj *c = get_channel_by_iface(iface, id);
+
+	if (!c)
+		return;
+
+	mutex_lock(&c->nq_mutex);
+	c->enqueue_halt = true;
+	mutex_unlock(&c->nq_mutex);
+}
+EXPORT_SYMBOL_GPL(most_stop_enqueue);
+
+/**
+ * most_resume_enqueue - allow core to enqueue MBOs again
+ * @iface: pointer to interface
+ * @id: channel id
+ *
+ * This clears the enqueue halt flag and enqueues all MBOs currently
+ * sitting in the wait fifo.
+ */
+void most_resume_enqueue(struct most_interface *iface, int id)
+{
+	struct most_c_obj *c = get_channel_by_iface(iface, id);
+
+	if (!c)
+		return;
+
+	mutex_lock(&c->nq_mutex);
+	c->enqueue_halt = false;
+	mutex_unlock(&c->nq_mutex);
+
+	wake_up_interruptible(&c->hdm_fifo_wq);
+}
+EXPORT_SYMBOL_GPL(most_resume_enqueue);
+
+static int __init most_init(void)
+{
+	int err;
+
+	pr_info("init()\n");
+	INIT_LIST_HEAD(&instance_list);
+	INIT_LIST_HEAD(&aim_list);
+	ida_init(&mdev_id);
+
+	err = bus_register(&most_bus);
+	if (err) {
+		pr_info("Cannot register most bus\n");
+		return err;
+	}
+
+	most_class = class_create(THIS_MODULE, "most");
+	if (IS_ERR(most_class)) {
+		pr_info("No udev support.\n");
+		err = PTR_ERR(most_class);
+		goto exit_bus;
+	}
+
+	err = driver_register(&mostcore);
+	if (err) {
+		pr_info("Cannot register core driver\n");
+		goto exit_class;
+	}
+
+	core_dev = device_create(most_class, NULL, 0, NULL, "mostcore");
+	if (IS_ERR(core_dev)) {
+		err = PTR_ERR(core_dev);
+		goto exit_driver;
+	}
+
+	most_aim_kset = kset_create_and_add("aims", NULL, &core_dev->kobj);
+	if (!most_aim_kset) {
+		err = -ENOMEM;
+		goto exit_class_container;
+	}
+
+	most_inst_kset = kset_create_and_add("devices", NULL, &core_dev->kobj);
+	if (!most_inst_kset) {
+		err = -ENOMEM;
+		goto exit_driver_kset;
+	}
+
+	return 0;
+
+exit_driver_kset:
+	kset_unregister(most_aim_kset);
+exit_class_container:
+	device_destroy(most_class, 0);
+exit_driver:
+	driver_unregister(&mostcore);
+exit_class:
+	class_destroy(most_class);
+exit_bus:
+	bus_unregister(&most_bus);
+	return err;
+}
+
+static void __exit most_exit(void)
+{
+	struct most_inst_obj *i, *i_tmp;
+	struct most_aim_obj *d, *d_tmp;
+
+	pr_info("exit core module\n");
+	list_for_each_entry_safe(d, d_tmp, &aim_list, list) {
+		destroy_most_aim_obj(d);
+	}
+
+	list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
+		list_del(&i->list);
+		destroy_most_inst_obj(i);
+	}
+	kset_unregister(most_inst_kset);
+	kset_unregister(most_aim_kset);
+	device_destroy(most_class, 0);
+	driver_unregister(&mostcore);
+	class_destroy(most_class);
+	bus_unregister(&most_bus);
+	ida_destroy(&mdev_id);
+}
+
+module_init(most_init);
+module_exit(most_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_DESCRIPTION("Core module of stacked MOST Linux driver");
diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h
new file mode 100644
index 0000000..a6e618c
--- /dev/null
+++ b/drivers/staging/most/core.h
@@ -0,0 +1,325 @@
+/*
+ * most.h - Interface between MostCore,
+ *   Hardware Dependent Module (HDM) and Application Interface Module (AIM).
+ *
+ * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+/*
+ * Authors:
+ *   Andrey Shvetsov <andrey.shvetsov@k2l.de>
+ *   Christian Gromm <christian.gromm@microchip.com>
+ *   Sebastian Graf
+ */
+
+#ifndef __MOST_CORE_H__
+#define __MOST_CORE_H__
+
+#include <linux/types.h>
+
+struct kobject;
+struct module;
+
+/**
+ * Interface type
+ */
+enum most_interface_type {
+	ITYPE_LOOPBACK = 1,
+	ITYPE_I2C,
+	ITYPE_I2S,
+	ITYPE_TSI,
+	ITYPE_HBI,
+	ITYPE_MEDIALB_DIM,
+	ITYPE_MEDIALB_DIM2,
+	ITYPE_USB,
+	ITYPE_PCIE
+};
+
+/**
+ * Channel direction.
+ */
+enum most_channel_direction {
+	MOST_CH_RX = 1 << 0,
+	MOST_CH_TX = 1 << 1,
+};
+
+/**
+ * Channel data type.
+ */
+enum most_channel_data_type {
+	MOST_CH_CONTROL = 1 << 0,
+	MOST_CH_ASYNC = 1 << 1,
+	MOST_CH_ISOC = 1 << 2,
+	MOST_CH_SYNC = 1 << 5,
+};
+
+enum mbo_status_flags {
+	/* MBO was processed successfully (data was send or received )*/
+	MBO_SUCCESS = 0,
+	/* The MBO contains wrong or missing information.  */
+	MBO_E_INVAL,
+	/* MBO was completed as HDM Channel will be closed */
+	MBO_E_CLOSE,
+};
+
+/**
+ * struct most_channel_capability - Channel capability
+ * @direction: Supported channel directions.
+ * The value is bitwise OR-combination of the values from the
+ * enumeration most_channel_direction. Zero is allowed value and means
+ * "channel may not be used".
+ * @data_type: Supported channel data types.
+ * The value is bitwise OR-combination of the values from the
+ * enumeration most_channel_data_type. Zero is allowed value and means
+ * "channel may not be used".
+ * @num_buffer_packet: Maximum number of buffers supported by this channel
+ * for packet data types (Async,Control,QoS)
+ * @buffer_size_packet: Maximum buffer size supported by this channel
+ * for packet data types (Async,Control,QoS)
+ * @num_buffer_streaming: Maximum number of buffers supported by this channel
+ * for streaming data types (Sync,AV Packetized)
+ * @buffer_size_streaming: Maximum buffer size supported by this channel
+ * for streaming data types (Sync,AV Packetized)
+ * @name_suffix: Optional suffix providean by an HDM that is attached to the
+ * regular channel name.
+ *
+ * Describes the capabilities of a MostCore channel like supported Data Types
+ * and directions. This information is provided by an HDM for the MostCore.
+ *
+ * The Core creates read only sysfs attribute files in
+ * /sys/devices/virtual/most/mostcore/devices/mdev-#/mdev#-ch#/ with the
+ * following attributes:
+ *	-available_directions
+ *	-available_datatypes
+ *	-number_of_packet_buffers
+ *	-number_of_stream_buffers
+ *	-size_of_packet_buffer
+ *	-size_of_stream_buffer
+ * where content of each file is a string with all supported properties of this
+ * very channel attribute.
+ */
+struct most_channel_capability {
+	u16 direction;
+	u16 data_type;
+	u16 num_buffers_packet;
+	u16 buffer_size_packet;
+	u16 num_buffers_streaming;
+	u16 buffer_size_streaming;
+	const char *name_suffix;
+};
+
+/**
+ * struct most_channel_config - stores channel configuration
+ * @direction: direction of the channel
+ * @data_type: data type travelling over this channel
+ * @num_buffers: number of buffers
+ * @buffer_size: size of a buffer for AIM.
+ * Buffer size may be cutted down by HDM in a configure callback
+ * to match to a given interface and channel type.
+ * @extra_len: additional buffer space for internal HDM purposes like padding.
+ * May be set by HDM in a configure callback if needed.
+ * @subbuffer_size: size of a subbuffer
+ * @packets_per_xact: number of MOST frames that are packet inside one USB
+ *		      packet. This is USB specific
+ *
+ * Describes the configuration for a MostCore channel. This information is
+ * provided from the MostCore to a HDM (like the Medusa PCIe Interface) as a
+ * parameter of the "configure" function call.
+ */
+struct most_channel_config {
+	enum most_channel_direction direction;
+	enum most_channel_data_type data_type;
+	u16 num_buffers;
+	u16 buffer_size;
+	u16 extra_len;
+	u16 subbuffer_size;
+	u16 packets_per_xact;
+};
+
+/*
+ * struct mbo - MOST Buffer Object.
+ * @context: context for core completion handler
+ * @priv: private data for HDM
+ *
+ *	public: documented fields that are used for the communications
+ *	between MostCore and HDMs
+ *
+ * @list: list head for use by the mbo's current owner
+ * @ifp: (in) associated interface instance
+ * @hdm_channel_id: (in) HDM channel instance
+ * @virt_address: (in) kernel virtual address of the buffer
+ * @bus_address: (in) bus address of the buffer
+ * @buffer_length: (in) buffer payload length
+ * @processed_length: (out) processed length
+ * @status: (out) transfer status
+ * @complete: (in) completion routine
+ *
+ * The MostCore allocates and initializes the MBO.
+ *
+ * The HDM receives MBO for transfer from MostCore with the call to enqueue().
+ * The HDM copies the data to- or from the buffer depending on configured
+ * channel direction, set "processed_length" and "status" and completes
+ * the transfer procedure by calling the completion routine.
+ *
+ * At the end the MostCore deallocates the MBO or recycles it for further
+ * transfers for the same or different HDM.
+ *
+ * Directions of usage:
+ * The core driver should never access any MBO fields (even if marked
+ * as "public") while the MBO is owned by an HDM. The ownership starts with
+ * the call of enqueue() and ends with the call of its complete() routine.
+ *
+ *					II.
+ * Every HDM attached to the core driver _must_ ensure that it returns any MBO
+ * it owns (due to a previous call to enqueue() by the core driver) before it
+ * de-registers an interface or gets unloaded from the kernel. If this direction
+ * is violated memory leaks will occur, since the core driver does _not_ track
+ * MBOs it is currently not in control of.
+ *
+ */
+struct mbo {
+	void *context;
+	void *priv;
+	struct list_head list;
+	struct most_interface *ifp;
+	int *num_buffers_ptr;
+	u16 hdm_channel_id;
+	void *virt_address;
+	dma_addr_t bus_address;
+	u16 buffer_length;
+	u16 processed_length;
+	enum mbo_status_flags status;
+	void (*complete)(struct mbo *);
+};
+
+/**
+ * Interface instance description.
+ *
+ * Describes one instance of an interface like Medusa PCIe or Vantage USB.
+ * This structure is allocated and initialized in the HDM. MostCore may not
+ * modify this structure.
+ *
+ * @interface Interface type. \sa most_interface_type.
+ * @description PRELIMINARY.
+ *   Unique description of the device instance from point of view of the
+ *   interface in free text form (ASCII).
+ *   It may be a hexadecimal presentation of the memory address for the MediaLB
+ *   IP or USB device ID with USB properties for USB interface, etc.
+ * @num_channels Number of channels and size of the channel_vector.
+ * @channel_vector Properties of the channels.
+ *   Array index represents channel ID by the driver.
+ * @configure Callback to change data type for the channel of the
+ *   interface instance. May be zero if the instance of the interface is not
+ *   configurable. Parameter channel_config describes direction and data
+ *   type for the channel, configured by the higher level. The content of
+ * @enqueue Delivers MBO to the HDM for processing.
+ *   After HDM completes Rx- or Tx- operation the processed MBO shall
+ *   be returned back to the MostCore using completion routine.
+ *   The reason to get the MBO delivered from the MostCore after the channel
+ *   is poisoned is the re-opening of the channel by the application.
+ *   In this case the HDM shall hold MBOs and service the channel as usual.
+ *   The HDM must be able to hold at least one MBO for each channel.
+ *   The callback returns a negative value on error, otherwise 0.
+ * @poison_channel Informs HDM about closing the channel. The HDM shall
+ *   cancel all transfers and synchronously or asynchronously return
+ *   all enqueued for this channel MBOs using the completion routine.
+ *   The callback returns a negative value on error, otherwise 0.
+ * @request_netinfo: triggers retrieving of network info from the HDM by
+ *   means of "Message exchange over MDP/MEP"
+ *   The call of the function request_netinfo with the parameter on_netinfo as
+ *   NULL prohibits use of the previously obtained function pointer.
+ * @priv Private field used by mostcore to store context information.
+ */
+struct most_interface {
+	struct module *mod;
+	enum most_interface_type interface;
+	const char *description;
+	int num_channels;
+	struct most_channel_capability *channel_vector;
+	int (*configure)(struct most_interface *iface, int channel_idx,
+			 struct most_channel_config *channel_config);
+	int (*enqueue)(struct most_interface *iface, int channel_idx,
+		       struct mbo *mbo);
+	int (*poison_channel)(struct most_interface *iface, int channel_idx);
+	void (*request_netinfo)(struct most_interface *iface, int channel_idx,
+				void (*on_netinfo)(struct most_interface *iface,
+						   unsigned char link_stat,
+						   unsigned char *mac_addr));
+	void *priv;
+};
+
+/**
+ * struct most_aim - identifies MOST device driver to mostcore
+ * @name: Driver name
+ * @probe_channel: function for core to notify driver about channel connection
+ * @disconnect_channel: callback function to disconnect a certain channel
+ * @rx_completion: completion handler for received packets
+ * @tx_completion: completion handler for transmitted packets
+ * @context: context pointer to be used by mostcore
+ */
+struct most_aim {
+	const char *name;
+	int (*probe_channel)(struct most_interface *iface, int channel_idx,
+			     struct most_channel_config *cfg,
+			     struct kobject *parent, char *name);
+	int (*disconnect_channel)(struct most_interface *iface,
+				  int channel_idx);
+	int (*rx_completion)(struct mbo *mbo);
+	int (*tx_completion)(struct most_interface *iface, int channel_idx);
+	void *context;
+};
+
+/**
+ * most_register_interface - Registers instance of the interface.
+ * @iface: Pointer to the interface instance description.
+ *
+ * Returns a pointer to the kobject of the generated instance.
+ *
+ * Note: HDM has to ensure that any reference held on the kobj is
+ * released before deregistering the interface.
+ */
+struct kobject *most_register_interface(struct most_interface *iface);
+
+/**
+ * Deregisters instance of the interface.
+ * @intf_instance Pointer to the interface instance description.
+ */
+void most_deregister_interface(struct most_interface *iface);
+void most_submit_mbo(struct mbo *mbo);
+
+/**
+ * most_stop_enqueue - prevents core from enqueing MBOs
+ * @iface: pointer to interface
+ * @channel_idx: channel index
+ */
+void most_stop_enqueue(struct most_interface *iface, int channel_idx);
+
+/**
+ * most_resume_enqueue - allow core to enqueue MBOs again
+ * @iface: pointer to interface
+ * @channel_idx: channel index
+ *
+ * This clears the enqueue halt flag and enqueues all MBOs currently
+ * in wait fifo.
+ */
+void most_resume_enqueue(struct most_interface *iface, int channel_idx);
+int most_register_aim(struct most_aim *aim);
+int most_deregister_aim(struct most_aim *aim);
+struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx,
+			 struct most_aim *);
+void most_put_mbo(struct mbo *mbo);
+int channel_has_mbo(struct most_interface *iface, int channel_idx,
+		    struct most_aim *aim);
+int most_start_channel(struct most_interface *iface, int channel_idx,
+		       struct most_aim *);
+int most_stop_channel(struct most_interface *iface, int channel_idx,
+		      struct most_aim *);
+
+#endif /* MOST_CORE_H_ */
diff --git a/drivers/staging/most/dim2/Kconfig b/drivers/staging/most/dim2/Kconfig
new file mode 100644
index 0000000..e39c4e5
--- /dev/null
+++ b/drivers/staging/most/dim2/Kconfig
@@ -0,0 +1,16 @@
+#
+# MediaLB configuration
+#
+
+config MOST_DIM2
+	tristate "DIM2"
+	depends on HAS_IOMEM
+
+	---help---
+	  Say Y here if you want to connect via MediaLB to network transceiver.
+	  This device driver is platform dependent and needs an additional
+	  platform driver to be installed. For more information contact
+	  maintainer of this driver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called most_dim2.
diff --git a/drivers/staging/most/dim2/Makefile b/drivers/staging/most/dim2/Makefile
new file mode 100644
index 0000000..66676f5
--- /dev/null
+++ b/drivers/staging/most/dim2/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_DIM2) += most_dim2.o
+
+most_dim2-objs := dim2.o hal.o sysfs.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c
new file mode 100644
index 0000000..cc8563f
--- /dev/null
+++ b/drivers/staging/most/dim2/dim2.c
@@ -0,0 +1,918 @@
+/*
+ * dim2.c - MediaLB DIM2 Hardware Dependent Module
+ *
+ * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+
+#include <most/core.h>
+#include "hal.h"
+#include "dim2.h"
+#include "errors.h"
+#include "sysfs.h"
+
+#define DMA_CHANNELS (32 - 1)  /* channel 0 is a system channel */
+
+#define MAX_BUFFERS_PACKET      32
+#define MAX_BUFFERS_STREAMING   32
+#define MAX_BUF_SIZE_PACKET     2048
+#define MAX_BUF_SIZE_STREAMING  (8 * 1024)
+
+/* command line parameter to select clock speed */
+static char *clock_speed;
+module_param(clock_speed, charp, 0000);
+MODULE_PARM_DESC(clock_speed, "MediaLB Clock Speed");
+
+/*
+ * The parameter representing the number of frames per sub-buffer for
+ * synchronous channels.  Valid values: [0 .. 6].
+ *
+ * The values 0, 1, 2, 3, 4, 5, 6 represent corresponding number of frames per
+ * sub-buffer 1, 2, 4, 8, 16, 32, 64.
+ */
+static u8 fcnt = 4;  /* (1 << fcnt) frames per subbuffer */
+module_param(fcnt, byte, 0000);
+MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a power of 2");
+
+static DEFINE_SPINLOCK(dim_lock);
+
+static void dim2_tasklet_fn(unsigned long data);
+static DECLARE_TASKLET(dim2_tasklet, dim2_tasklet_fn, 0);
+
+/**
+ * struct hdm_channel - private structure to keep channel specific data
+ * @is_initialized: identifier to know whether the channel is initialized
+ * @ch: HAL specific channel data
+ * @pending_list: list to keep MBO's before starting transfer
+ * @started_list: list to keep MBO's after starting transfer
+ * @direction: channel direction (TX or RX)
+ * @data_type: channel data type
+ */
+struct hdm_channel {
+	char name[sizeof "caNNN"];
+	bool is_initialized;
+	struct dim_channel ch;
+	struct list_head pending_list;	/* before dim_enqueue_buffer() */
+	struct list_head started_list;	/* after dim_enqueue_buffer() */
+	enum most_channel_direction direction;
+	enum most_channel_data_type data_type;
+};
+
+/**
+ * struct dim2_hdm - private structure to keep interface specific data
+ * @hch: an array of channel specific data
+ * @most_iface: most interface structure
+ * @capabilities: an array of channel capability data
+ * @io_base: I/O register base address
+ * @clk_speed: user selectable (through command line parameter) clock speed
+ * @netinfo_task: thread to deliver network status
+ * @netinfo_waitq: waitq for the thread to sleep
+ * @deliver_netinfo: to identify whether network status received
+ * @mac_addrs: INIC mac address
+ * @link_state: network link state
+ * @atx_idx: index of async tx channel
+ */
+struct dim2_hdm {
+	struct hdm_channel hch[DMA_CHANNELS];
+	struct most_channel_capability capabilities[DMA_CHANNELS];
+	struct most_interface most_iface;
+	char name[16 + sizeof "dim2-"];
+	void __iomem *io_base;
+	int clk_speed;
+	struct task_struct *netinfo_task;
+	wait_queue_head_t netinfo_waitq;
+	int deliver_netinfo;
+	unsigned char mac_addrs[6];
+	unsigned char link_state;
+	int atx_idx;
+	struct medialb_bus bus;
+	void (*on_netinfo)(struct most_interface *,
+			   unsigned char, unsigned char *);
+};
+
+#define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface)
+
+/* Macro to identify a network status message */
+#define PACKET_IS_NET_INFO(p)  \
+	(((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \
+	 ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A))
+
+bool dim2_sysfs_get_state_cb(void)
+{
+	bool state;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dim_lock, flags);
+	state = dim_get_lock_state();
+	spin_unlock_irqrestore(&dim_lock, flags);
+
+	return state;
+}
+
+/**
+ * dimcb_io_read - callback from HAL to read an I/O register
+ * @ptr32: register address
+ */
+u32 dimcb_io_read(u32 __iomem *ptr32)
+{
+	return readl(ptr32);
+}
+
+/**
+ * dimcb_io_write - callback from HAL to write value to an I/O register
+ * @ptr32: register address
+ * @value: value to write
+ */
+void dimcb_io_write(u32 __iomem *ptr32, u32 value)
+{
+	writel(value, ptr32);
+}
+
+/**
+ * dimcb_on_error - callback from HAL to report miscommunication between
+ * HDM and HAL
+ * @error_id: Error ID
+ * @error_message: Error message. Some text in a free format
+ */
+void dimcb_on_error(u8 error_id, const char *error_message)
+{
+	pr_err("dimcb_on_error: error_id - %d, error_message - %s\n", error_id,
+	       error_message);
+}
+
+/**
+ * startup_dim - initialize the dim2 interface
+ * @pdev: platform device
+ *
+ * Get the value of command line parameter "clock_speed" if given or use the
+ * default value, enable the clock and PLL, and initialize the dim2 interface.
+ */
+static int startup_dim(struct platform_device *pdev)
+{
+	struct dim2_hdm *dev = platform_get_drvdata(pdev);
+	struct dim2_platform_data *pdata = pdev->dev.platform_data;
+	u8 hal_ret;
+
+	dev->clk_speed = -1;
+
+	if (clock_speed) {
+		if (!strcmp(clock_speed, "256fs"))
+			dev->clk_speed = CLK_256FS;
+		else if (!strcmp(clock_speed, "512fs"))
+			dev->clk_speed = CLK_512FS;
+		else if (!strcmp(clock_speed, "1024fs"))
+			dev->clk_speed = CLK_1024FS;
+		else if (!strcmp(clock_speed, "2048fs"))
+			dev->clk_speed = CLK_2048FS;
+		else if (!strcmp(clock_speed, "3072fs"))
+			dev->clk_speed = CLK_3072FS;
+		else if (!strcmp(clock_speed, "4096fs"))
+			dev->clk_speed = CLK_4096FS;
+		else if (!strcmp(clock_speed, "6144fs"))
+			dev->clk_speed = CLK_6144FS;
+		else if (!strcmp(clock_speed, "8192fs"))
+			dev->clk_speed = CLK_8192FS;
+	}
+
+	if (dev->clk_speed == -1) {
+		pr_info("Bad or missing clock speed parameter, using default value: 3072fs\n");
+		dev->clk_speed = CLK_3072FS;
+	} else {
+		pr_info("Selected clock speed: %s\n", clock_speed);
+	}
+	if (pdata && pdata->init) {
+		int ret = pdata->init(pdata, dev->io_base, dev->clk_speed);
+
+		if (ret)
+			return ret;
+	}
+
+	pr_info("sync: num of frames per sub-buffer: %u\n", fcnt);
+	hal_ret = dim_startup(dev->io_base, dev->clk_speed, fcnt);
+	if (hal_ret != DIM_NO_ERROR) {
+		pr_err("dim_startup failed: %d\n", hal_ret);
+		if (pdata && pdata->destroy)
+			pdata->destroy(pdata);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/**
+ * try_start_dim_transfer - try to transfer a buffer on a channel
+ * @hdm_ch: channel specific data
+ *
+ * Transfer a buffer from pending_list if the channel is ready
+ */
+static int try_start_dim_transfer(struct hdm_channel *hdm_ch)
+{
+	u16 buf_size;
+	struct list_head *head = &hdm_ch->pending_list;
+	struct mbo *mbo;
+	unsigned long flags;
+	struct dim_ch_state_t st;
+
+	BUG_ON(!hdm_ch);
+	BUG_ON(!hdm_ch->is_initialized);
+
+	spin_lock_irqsave(&dim_lock, flags);
+	if (list_empty(head)) {
+		spin_unlock_irqrestore(&dim_lock, flags);
+		return -EAGAIN;
+	}
+
+	if (!dim_get_channel_state(&hdm_ch->ch, &st)->ready) {
+		spin_unlock_irqrestore(&dim_lock, flags);
+		return -EAGAIN;
+	}
+
+	mbo = list_first_entry(head, struct mbo, list);
+	buf_size = mbo->buffer_length;
+
+	if (dim_dbr_space(&hdm_ch->ch) < buf_size) {
+		spin_unlock_irqrestore(&dim_lock, flags);
+		return -EAGAIN;
+	}
+
+	BUG_ON(mbo->bus_address == 0);
+	if (!dim_enqueue_buffer(&hdm_ch->ch, mbo->bus_address, buf_size)) {
+		list_del(head->next);
+		spin_unlock_irqrestore(&dim_lock, flags);
+		mbo->processed_length = 0;
+		mbo->status = MBO_E_INVAL;
+		mbo->complete(mbo);
+		return -EFAULT;
+	}
+
+	list_move_tail(head->next, &hdm_ch->started_list);
+	spin_unlock_irqrestore(&dim_lock, flags);
+
+	return 0;
+}
+
+/**
+ * deliver_netinfo_thread - thread to deliver network status to mostcore
+ * @data: private data
+ *
+ * Wait for network status and deliver it to mostcore once it is received
+ */
+static int deliver_netinfo_thread(void *data)
+{
+	struct dim2_hdm *dev = data;
+
+	while (!kthread_should_stop()) {
+		wait_event_interruptible(dev->netinfo_waitq,
+					 dev->deliver_netinfo ||
+					 kthread_should_stop());
+
+		if (dev->deliver_netinfo) {
+			dev->deliver_netinfo--;
+			if (dev->on_netinfo) {
+				dev->on_netinfo(&dev->most_iface,
+						dev->link_state,
+						dev->mac_addrs);
+			}
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * retrieve_netinfo - retrieve network status from received buffer
+ * @dev: private data
+ * @mbo: received MBO
+ *
+ * Parse the message in buffer and get node address, link state, MAC address.
+ * Wake up a thread to deliver this status to mostcore
+ */
+static void retrieve_netinfo(struct dim2_hdm *dev, struct mbo *mbo)
+{
+	u8 *data = mbo->virt_address;
+
+	pr_info("Node Address: 0x%03x\n", (u16)data[16] << 8 | data[17]);
+	dev->link_state = data[18];
+	pr_info("NIState: %d\n", dev->link_state);
+	memcpy(dev->mac_addrs, data + 19, 6);
+	dev->deliver_netinfo++;
+	wake_up_interruptible(&dev->netinfo_waitq);
+}
+
+/**
+ * service_done_flag - handle completed buffers
+ * @dev: private data
+ * @ch_idx: channel index
+ *
+ * Return back the completed buffers to mostcore, using completion callback
+ */
+static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
+{
+	struct hdm_channel *hdm_ch = dev->hch + ch_idx;
+	struct dim_ch_state_t st;
+	struct list_head *head;
+	struct mbo *mbo;
+	int done_buffers;
+	unsigned long flags;
+	u8 *data;
+
+	BUG_ON(!hdm_ch);
+	BUG_ON(!hdm_ch->is_initialized);
+
+	spin_lock_irqsave(&dim_lock, flags);
+
+	done_buffers = dim_get_channel_state(&hdm_ch->ch, &st)->done_buffers;
+	if (!done_buffers) {
+		spin_unlock_irqrestore(&dim_lock, flags);
+		return;
+	}
+
+	if (!dim_detach_buffers(&hdm_ch->ch, done_buffers)) {
+		spin_unlock_irqrestore(&dim_lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(&dim_lock, flags);
+
+	head = &hdm_ch->started_list;
+
+	while (done_buffers) {
+		spin_lock_irqsave(&dim_lock, flags);
+		if (list_empty(head)) {
+			spin_unlock_irqrestore(&dim_lock, flags);
+			pr_crit("hard error: started_mbo list is empty whereas DIM2 has sent buffers\n");
+			break;
+		}
+
+		mbo = list_first_entry(head, struct mbo, list);
+		list_del(head->next);
+		spin_unlock_irqrestore(&dim_lock, flags);
+
+		data = mbo->virt_address;
+
+		if (hdm_ch->data_type == MOST_CH_ASYNC &&
+		    hdm_ch->direction == MOST_CH_RX &&
+		    PACKET_IS_NET_INFO(data)) {
+			retrieve_netinfo(dev, mbo);
+
+			spin_lock_irqsave(&dim_lock, flags);
+			list_add_tail(&mbo->list, &hdm_ch->pending_list);
+			spin_unlock_irqrestore(&dim_lock, flags);
+		} else {
+			if (hdm_ch->data_type == MOST_CH_CONTROL ||
+			    hdm_ch->data_type == MOST_CH_ASYNC) {
+				u32 const data_size =
+					(u32)data[0] * 256 + data[1] + 2;
+
+				mbo->processed_length =
+					min_t(u32, data_size,
+					      mbo->buffer_length);
+			} else {
+				mbo->processed_length = mbo->buffer_length;
+			}
+			mbo->status = MBO_SUCCESS;
+			mbo->complete(mbo);
+		}
+
+		done_buffers--;
+	}
+}
+
+static struct dim_channel **get_active_channels(struct dim2_hdm *dev,
+						struct dim_channel **buffer)
+{
+	int idx = 0;
+	int ch_idx;
+
+	for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) {
+		if (dev->hch[ch_idx].is_initialized)
+			buffer[idx++] = &dev->hch[ch_idx].ch;
+	}
+	buffer[idx++] = NULL;
+
+	return buffer;
+}
+
+static irqreturn_t dim2_mlb_isr(int irq, void *_dev)
+{
+	struct dim2_hdm *dev = _dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dim_lock, flags);
+	dim_service_mlb_int_irq();
+	spin_unlock_irqrestore(&dim_lock, flags);
+
+	if (dev->atx_idx >= 0 && dev->hch[dev->atx_idx].is_initialized)
+		while (!try_start_dim_transfer(dev->hch + dev->atx_idx))
+			continue;
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * dim2_tasklet_fn - tasklet function
+ * @data: private data
+ *
+ * Service each initialized channel, if needed
+ */
+static void dim2_tasklet_fn(unsigned long data)
+{
+	struct dim2_hdm *dev = (struct dim2_hdm *)data;
+	unsigned long flags;
+	int ch_idx;
+
+	for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) {
+		if (!dev->hch[ch_idx].is_initialized)
+			continue;
+
+		spin_lock_irqsave(&dim_lock, flags);
+		dim_service_channel(&dev->hch[ch_idx].ch);
+		spin_unlock_irqrestore(&dim_lock, flags);
+
+		service_done_flag(dev, ch_idx);
+		while (!try_start_dim_transfer(dev->hch + ch_idx))
+			continue;
+	}
+}
+
+/**
+ * dim2_ahb_isr - interrupt service routine
+ * @irq: irq number
+ * @_dev: private data
+ *
+ * Acknowledge the interrupt and schedule a tasklet to service channels.
+ * Return IRQ_HANDLED.
+ */
+static irqreturn_t dim2_ahb_isr(int irq, void *_dev)
+{
+	struct dim2_hdm *dev = _dev;
+	struct dim_channel *buffer[DMA_CHANNELS + 1];
+	unsigned long flags;
+
+	spin_lock_irqsave(&dim_lock, flags);
+	dim_service_ahb_int_irq(get_active_channels(dev, buffer));
+	spin_unlock_irqrestore(&dim_lock, flags);
+
+	dim2_tasklet.data = (unsigned long)dev;
+	tasklet_schedule(&dim2_tasklet);
+	return IRQ_HANDLED;
+}
+
+/**
+ * complete_all_mbos - complete MBO's in a list
+ * @head: list head
+ *
+ * Delete all the entries in list and return back MBO's to mostcore using
+ * completion call back.
+ */
+static void complete_all_mbos(struct list_head *head)
+{
+	unsigned long flags;
+	struct mbo *mbo;
+
+	for (;;) {
+		spin_lock_irqsave(&dim_lock, flags);
+		if (list_empty(head)) {
+			spin_unlock_irqrestore(&dim_lock, flags);
+			break;
+		}
+
+		mbo = list_first_entry(head, struct mbo, list);
+		list_del(head->next);
+		spin_unlock_irqrestore(&dim_lock, flags);
+
+		mbo->processed_length = 0;
+		mbo->status = MBO_E_CLOSE;
+		mbo->complete(mbo);
+	}
+}
+
+/**
+ * configure_channel - initialize a channel
+ * @iface: interface the channel belongs to
+ * @channel: channel to be configured
+ * @channel_config: structure that holds the configuration information
+ *
+ * Receives configuration information from mostcore and initialize
+ * the corresponding channel. Return 0 on success, negative on failure.
+ */
+static int configure_channel(struct most_interface *most_iface, int ch_idx,
+			     struct most_channel_config *ccfg)
+{
+	struct dim2_hdm *dev = iface_to_hdm(most_iface);
+	bool const is_tx = ccfg->direction == MOST_CH_TX;
+	u16 const sub_size = ccfg->subbuffer_size;
+	u16 const buf_size = ccfg->buffer_size;
+	u16 new_size;
+	unsigned long flags;
+	u8 hal_ret;
+	int const ch_addr = ch_idx * 2 + 2;
+	struct hdm_channel *const hdm_ch = dev->hch + ch_idx;
+
+	BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
+
+	if (hdm_ch->is_initialized)
+		return -EPERM;
+
+	switch (ccfg->data_type) {
+	case MOST_CH_CONTROL:
+		new_size = dim_norm_ctrl_async_buffer_size(buf_size);
+		if (new_size == 0) {
+			pr_err("%s: too small buffer size\n", hdm_ch->name);
+			return -EINVAL;
+		}
+		ccfg->buffer_size = new_size;
+		if (new_size != buf_size)
+			pr_warn("%s: fixed buffer size (%d -> %d)\n",
+				hdm_ch->name, buf_size, new_size);
+		spin_lock_irqsave(&dim_lock, flags);
+		hal_ret = dim_init_control(&hdm_ch->ch, is_tx, ch_addr,
+					   is_tx ? new_size * 2 : new_size);
+		break;
+	case MOST_CH_ASYNC:
+		new_size = dim_norm_ctrl_async_buffer_size(buf_size);
+		if (new_size == 0) {
+			pr_err("%s: too small buffer size\n", hdm_ch->name);
+			return -EINVAL;
+		}
+		ccfg->buffer_size = new_size;
+		if (new_size != buf_size)
+			pr_warn("%s: fixed buffer size (%d -> %d)\n",
+				hdm_ch->name, buf_size, new_size);
+		spin_lock_irqsave(&dim_lock, flags);
+		hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr,
+					 is_tx ? new_size * 2 : new_size);
+		break;
+	case MOST_CH_ISOC:
+		new_size = dim_norm_isoc_buffer_size(buf_size, sub_size);
+		if (new_size == 0) {
+			pr_err("%s: invalid sub-buffer size or too small buffer size\n",
+			       hdm_ch->name);
+			return -EINVAL;
+		}
+		ccfg->buffer_size = new_size;
+		if (new_size != buf_size)
+			pr_warn("%s: fixed buffer size (%d -> %d)\n",
+				hdm_ch->name, buf_size, new_size);
+		spin_lock_irqsave(&dim_lock, flags);
+		hal_ret = dim_init_isoc(&hdm_ch->ch, is_tx, ch_addr, sub_size);
+		break;
+	case MOST_CH_SYNC:
+		new_size = dim_norm_sync_buffer_size(buf_size, sub_size);
+		if (new_size == 0) {
+			pr_err("%s: invalid sub-buffer size or too small buffer size\n",
+			       hdm_ch->name);
+			return -EINVAL;
+		}
+		ccfg->buffer_size = new_size;
+		if (new_size != buf_size)
+			pr_warn("%s: fixed buffer size (%d -> %d)\n",
+				hdm_ch->name, buf_size, new_size);
+		spin_lock_irqsave(&dim_lock, flags);
+		hal_ret = dim_init_sync(&hdm_ch->ch, is_tx, ch_addr, sub_size);
+		break;
+	default:
+		pr_err("%s: configure failed, bad channel type: %d\n",
+		       hdm_ch->name, ccfg->data_type);
+		return -EINVAL;
+	}
+
+	if (hal_ret != DIM_NO_ERROR) {
+		spin_unlock_irqrestore(&dim_lock, flags);
+		pr_err("%s: configure failed (%d), type: %d, is_tx: %d\n",
+		       hdm_ch->name, hal_ret, ccfg->data_type, (int)is_tx);
+		return -ENODEV;
+	}
+
+	hdm_ch->data_type = ccfg->data_type;
+	hdm_ch->direction = ccfg->direction;
+	hdm_ch->is_initialized = true;
+
+	if (hdm_ch->data_type == MOST_CH_ASYNC &&
+	    hdm_ch->direction == MOST_CH_TX &&
+	    dev->atx_idx < 0)
+		dev->atx_idx = ch_idx;
+
+	spin_unlock_irqrestore(&dim_lock, flags);
+
+	return 0;
+}
+
+/**
+ * enqueue - enqueue a buffer for data transfer
+ * @iface: intended interface
+ * @channel: ID of the channel the buffer is intended for
+ * @mbo: pointer to the buffer object
+ *
+ * Push the buffer into pending_list and try to transfer one buffer from
+ * pending_list. Return 0 on success, negative on failure.
+ */
+static int enqueue(struct most_interface *most_iface, int ch_idx,
+		   struct mbo *mbo)
+{
+	struct dim2_hdm *dev = iface_to_hdm(most_iface);
+	struct hdm_channel *hdm_ch = dev->hch + ch_idx;
+	unsigned long flags;
+
+	BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
+
+	if (!hdm_ch->is_initialized)
+		return -EPERM;
+
+	if (mbo->bus_address == 0)
+		return -EFAULT;
+
+	spin_lock_irqsave(&dim_lock, flags);
+	list_add_tail(&mbo->list, &hdm_ch->pending_list);
+	spin_unlock_irqrestore(&dim_lock, flags);
+
+	(void)try_start_dim_transfer(hdm_ch);
+
+	return 0;
+}
+
+/**
+ * request_netinfo - triggers retrieving of network info
+ * @iface: pointer to the interface
+ * @channel_id: corresponding channel ID
+ *
+ * Send a command to INIC which triggers retrieving of network info by means of
+ * "Message exchange over MDP/MEP". Return 0 on success, negative on failure.
+ */
+static void request_netinfo(struct most_interface *most_iface, int ch_idx,
+			    void (*on_netinfo)(struct most_interface *,
+					       unsigned char, unsigned char *))
+{
+	struct dim2_hdm *dev = iface_to_hdm(most_iface);
+	struct mbo *mbo;
+	u8 *data;
+
+	dev->on_netinfo = on_netinfo;
+	if (!on_netinfo)
+		return;
+
+	if (dev->atx_idx < 0) {
+		pr_err("Async Tx Not initialized\n");
+		return;
+	}
+
+	mbo = most_get_mbo(&dev->most_iface, dev->atx_idx, NULL);
+	if (!mbo)
+		return;
+
+	mbo->buffer_length = 5;
+
+	data = mbo->virt_address;
+
+	data[0] = 0x00; /* PML High byte */
+	data[1] = 0x03; /* PML Low byte */
+	data[2] = 0x02; /* PMHL */
+	data[3] = 0x08; /* FPH */
+	data[4] = 0x40; /* FMF (FIFO cmd msg - Triggers NAOverMDP) */
+
+	most_submit_mbo(mbo);
+}
+
+/**
+ * poison_channel - poison buffers of a channel
+ * @iface: pointer to the interface the channel to be poisoned belongs to
+ * @channel_id: corresponding channel ID
+ *
+ * Destroy a channel and complete all the buffers in both started_list &
+ * pending_list. Return 0 on success, negative on failure.
+ */
+static int poison_channel(struct most_interface *most_iface, int ch_idx)
+{
+	struct dim2_hdm *dev = iface_to_hdm(most_iface);
+	struct hdm_channel *hdm_ch = dev->hch + ch_idx;
+	unsigned long flags;
+	u8 hal_ret;
+	int ret = 0;
+
+	BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
+
+	if (!hdm_ch->is_initialized)
+		return -EPERM;
+
+	tasklet_disable(&dim2_tasklet);
+	spin_lock_irqsave(&dim_lock, flags);
+	hal_ret = dim_destroy_channel(&hdm_ch->ch);
+	hdm_ch->is_initialized = false;
+	if (ch_idx == dev->atx_idx)
+		dev->atx_idx = -1;
+	spin_unlock_irqrestore(&dim_lock, flags);
+	tasklet_enable(&dim2_tasklet);
+	if (hal_ret != DIM_NO_ERROR) {
+		pr_err("HAL Failed to close channel %s\n", hdm_ch->name);
+		ret = -EFAULT;
+	}
+
+	complete_all_mbos(&hdm_ch->started_list);
+	complete_all_mbos(&hdm_ch->pending_list);
+
+	return ret;
+}
+
+/*
+ * dim2_probe - dim2 probe handler
+ * @pdev: platform device structure
+ *
+ * Register the dim2 interface with mostcore and initialize it.
+ * Return 0 on success, negative on failure.
+ */
+static int dim2_probe(struct platform_device *pdev)
+{
+	struct dim2_hdm *dev;
+	struct resource *res;
+	int ret, i;
+	struct kobject *kobj;
+	int irq;
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->atx_idx = -1;
+
+	platform_set_drvdata(pdev, dev);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dev->io_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(dev->io_base))
+		return PTR_ERR(dev->io_base);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "failed to get ahb0_int irq: %d\n", irq);
+		return irq;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, dim2_ahb_isr, 0,
+			       "dim2_ahb0_int", dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request ahb0_int irq %d\n", irq);
+		return ret;
+	}
+
+	irq = platform_get_irq(pdev, 1);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "failed to get mlb_int irq: %d\n", irq);
+		return irq;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, dim2_mlb_isr, 0,
+			       "dim2_mlb_int", dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request mlb_int irq %d\n", irq);
+		return ret;
+	}
+
+	init_waitqueue_head(&dev->netinfo_waitq);
+	dev->deliver_netinfo = 0;
+	dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev,
+					"dim2_netinfo");
+	if (IS_ERR(dev->netinfo_task))
+		return PTR_ERR(dev->netinfo_task);
+
+	for (i = 0; i < DMA_CHANNELS; i++) {
+		struct most_channel_capability *cap = dev->capabilities + i;
+		struct hdm_channel *hdm_ch = dev->hch + i;
+
+		INIT_LIST_HEAD(&hdm_ch->pending_list);
+		INIT_LIST_HEAD(&hdm_ch->started_list);
+		hdm_ch->is_initialized = false;
+		snprintf(hdm_ch->name, sizeof(hdm_ch->name), "ca%d", i * 2 + 2);
+
+		cap->name_suffix = hdm_ch->name;
+		cap->direction = MOST_CH_RX | MOST_CH_TX;
+		cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
+				 MOST_CH_ISOC | MOST_CH_SYNC;
+		cap->num_buffers_packet = MAX_BUFFERS_PACKET;
+		cap->buffer_size_packet = MAX_BUF_SIZE_PACKET;
+		cap->num_buffers_streaming = MAX_BUFFERS_STREAMING;
+		cap->buffer_size_streaming = MAX_BUF_SIZE_STREAMING;
+	}
+
+	{
+		const char *fmt;
+
+		if (sizeof(res->start) == sizeof(long long))
+			fmt = "dim2-%016llx";
+		else if (sizeof(res->start) == sizeof(long))
+			fmt = "dim2-%016lx";
+		else
+			fmt = "dim2-%016x";
+
+		snprintf(dev->name, sizeof(dev->name), fmt, res->start);
+	}
+
+	dev->most_iface.interface = ITYPE_MEDIALB_DIM2;
+	dev->most_iface.description = dev->name;
+	dev->most_iface.num_channels = DMA_CHANNELS;
+	dev->most_iface.channel_vector = dev->capabilities;
+	dev->most_iface.configure = configure_channel;
+	dev->most_iface.enqueue = enqueue;
+	dev->most_iface.poison_channel = poison_channel;
+	dev->most_iface.request_netinfo = request_netinfo;
+
+	kobj = most_register_interface(&dev->most_iface);
+	if (IS_ERR(kobj)) {
+		ret = PTR_ERR(kobj);
+		dev_err(&pdev->dev, "failed to register MOST interface\n");
+		goto err_stop_thread;
+	}
+
+	ret = dim2_sysfs_probe(&dev->bus, kobj);
+	if (ret)
+		goto err_unreg_iface;
+
+	ret = startup_dim(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize DIM2\n");
+		goto err_destroy_bus;
+	}
+
+	return 0;
+
+err_destroy_bus:
+	dim2_sysfs_destroy(&dev->bus);
+err_unreg_iface:
+	most_deregister_interface(&dev->most_iface);
+err_stop_thread:
+	kthread_stop(dev->netinfo_task);
+
+	return ret;
+}
+
+/**
+ * dim2_remove - dim2 remove handler
+ * @pdev: platform device structure
+ *
+ * Unregister the interface from mostcore
+ */
+static int dim2_remove(struct platform_device *pdev)
+{
+	struct dim2_hdm *dev = platform_get_drvdata(pdev);
+	struct dim2_platform_data *pdata = pdev->dev.platform_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dim_lock, flags);
+	dim_shutdown();
+	spin_unlock_irqrestore(&dim_lock, flags);
+
+	if (pdata && pdata->destroy)
+		pdata->destroy(pdata);
+
+	dim2_sysfs_destroy(&dev->bus);
+	most_deregister_interface(&dev->most_iface);
+	kthread_stop(dev->netinfo_task);
+
+	/*
+	 * break link to local platform_device_id struct
+	 * to prevent crash by unload platform device module
+	 */
+	pdev->id_entry = NULL;
+
+	return 0;
+}
+
+static const struct platform_device_id dim2_id[] = {
+	{ "medialb_dim2" },
+	{ }, /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(platform, dim2_id);
+
+static struct platform_driver dim2_driver = {
+	.probe = dim2_probe,
+	.remove = dim2_remove,
+	.id_table = dim2_id,
+	.driver = {
+		.name = "hdm_dim2",
+	},
+};
+
+module_platform_driver(dim2_driver);
+
+MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_DESCRIPTION("MediaLB DIM2 Hardware Dependent Module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/dim2/dim2.h b/drivers/staging/most/dim2/dim2.h
new file mode 100644
index 0000000..7fff99c
--- /dev/null
+++ b/drivers/staging/most/dim2/dim2.h
@@ -0,0 +1,27 @@
+/*
+ * dim2.h - MediaLB DIM2 HDM Header
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#ifndef DIM2_HDM_H
+#define	DIM2_HDM_H
+
+struct device;
+
+/* platform dependent data for dim2 interface */
+struct dim2_platform_data {
+	int (*init)(struct dim2_platform_data *pd, void __iomem *io_base,
+		    int clk_speed);
+	void (*destroy)(struct dim2_platform_data *pd);
+	void *priv;
+};
+
+#endif	/* DIM2_HDM_H */
diff --git a/drivers/staging/most/dim2/errors.h b/drivers/staging/most/dim2/errors.h
new file mode 100644
index 0000000..0cd8400
--- /dev/null
+++ b/drivers/staging/most/dim2/errors.h
@@ -0,0 +1,57 @@
+/*
+ * errors.h - Definitions of errors for DIM2 HAL API
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#ifndef _MOST_DIM_ERRORS_H
+#define _MOST_DIM_ERRORS_H
+
+/**
+ * MOST DIM errors.
+ */
+enum dim_errors_t {
+	/** Not an error */
+	DIM_NO_ERROR = 0,
+
+	/** Bad base address for DIM2 IP */
+	DIM_INIT_ERR_DIM_ADDR = 0x10,
+
+	/**< Bad MediaLB clock */
+	DIM_INIT_ERR_MLB_CLOCK,
+
+	/** Bad channel address */
+	DIM_INIT_ERR_CHANNEL_ADDRESS,
+
+	/** Out of DBR memory */
+	DIM_INIT_ERR_OUT_OF_MEMORY,
+
+	/** DIM API is called while DIM is not initialized successfully */
+	DIM_ERR_DRIVER_NOT_INITIALIZED = 0x20,
+
+	/**
+	 * Configuration does not respect hardware limitations
+	 * for isochronous or synchronous channels
+	 */
+	DIM_ERR_BAD_CONFIG,
+
+	/**
+	 * Buffer size does not respect hardware limitations
+	 * for isochronous or synchronous channels
+	 */
+	DIM_ERR_BAD_BUFFER_SIZE,
+
+	DIM_ERR_UNDERFLOW,
+
+	DIM_ERR_OVERFLOW,
+};
+
+#endif /* _MOST_DIM_ERRORS_H */
diff --git a/drivers/staging/most/dim2/hal.c b/drivers/staging/most/dim2/hal.c
new file mode 100644
index 0000000..9f00ecc
--- /dev/null
+++ b/drivers/staging/most/dim2/hal.c
@@ -0,0 +1,985 @@
+/*
+ * hal.c - DIM2 HAL implementation
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
+
+#include "hal.h"
+#include "errors.h"
+#include "reg.h"
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+
+/*
+ * Size factor for isochronous DBR buffer.
+ * Minimal value is 3.
+ */
+#define ISOC_DBR_FACTOR 3u
+
+/*
+ * Number of 32-bit units for DBR map.
+ *
+ * 1: block size is 512, max allocation is 16K
+ * 2: block size is 256, max allocation is 8K
+ * 4: block size is 128, max allocation is 4K
+ * 8: block size is 64, max allocation is 2K
+ *
+ * Min allocated space is block size.
+ * Max possible allocated space is 32 blocks.
+ */
+#define DBR_MAP_SIZE 2
+
+/* -------------------------------------------------------------------------- */
+/* not configurable area */
+
+#define CDT 0x00
+#define ADT 0x40
+#define MLB_CAT 0x80
+#define AHB_CAT 0x88
+
+#define DBR_SIZE  (16 * 1024) /* specified by IP */
+#define DBR_BLOCK_SIZE  (DBR_SIZE / 32 / DBR_MAP_SIZE)
+
+#define ROUND_UP_TO(x, d)  (DIV_ROUND_UP(x, (d)) * (d))
+
+/* -------------------------------------------------------------------------- */
+/* generic helper functions and macros */
+
+static inline u32 bit_mask(u8 position)
+{
+	return (u32)1 << position;
+}
+
+static inline bool dim_on_error(u8 error_id, const char *error_message)
+{
+	dimcb_on_error(error_id, error_message);
+	return false;
+}
+
+/* -------------------------------------------------------------------------- */
+/* types and local variables */
+
+struct async_tx_dbr {
+	u8 ch_addr;
+	u16 rpc;
+	u16 wpc;
+	u16 rest_size;
+	u16 sz_queue[CDT0_RPC_MASK + 1];
+};
+
+struct lld_global_vars_t {
+	bool dim_is_initialized;
+	bool mcm_is_initialized;
+	struct dim2_regs __iomem *dim2; /* DIM2 core base address */
+	struct async_tx_dbr atx_dbr;
+	u32 fcnt;
+	u32 dbr_map[DBR_MAP_SIZE];
+};
+
+static struct lld_global_vars_t g = { false };
+
+/* -------------------------------------------------------------------------- */
+
+static int dbr_get_mask_size(u16 size)
+{
+	int i;
+
+	for (i = 0; i < 6; i++)
+		if (size <= (DBR_BLOCK_SIZE << i))
+			return 1 << i;
+	return 0;
+}
+
+/**
+ * Allocates DBR memory.
+ * @param size Allocating memory size.
+ * @return Offset in DBR memory by success or DBR_SIZE if out of memory.
+ */
+static int alloc_dbr(u16 size)
+{
+	int mask_size;
+	int i, block_idx = 0;
+
+	if (size <= 0)
+		return DBR_SIZE; /* out of memory */
+
+	mask_size = dbr_get_mask_size(size);
+	if (mask_size == 0)
+		return DBR_SIZE; /* out of memory */
+
+	for (i = 0; i < DBR_MAP_SIZE; i++) {
+		u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE);
+		u32 mask = ~((~(u32)0) << blocks);
+
+		do {
+			if ((g.dbr_map[i] & mask) == 0) {
+				g.dbr_map[i] |= mask;
+				return block_idx * DBR_BLOCK_SIZE;
+			}
+			block_idx += mask_size;
+			/* do shift left with 2 steps in case mask_size == 32 */
+			mask <<= mask_size - 1;
+		} while ((mask <<= 1) != 0);
+	}
+
+	return DBR_SIZE; /* out of memory */
+}
+
+static void free_dbr(int offs, int size)
+{
+	int block_idx = offs / DBR_BLOCK_SIZE;
+	u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE);
+	u32 mask = ~((~(u32)0) << blocks);
+
+	mask <<= block_idx % 32;
+	g.dbr_map[block_idx / 32] &= ~mask;
+}
+
+/* -------------------------------------------------------------------------- */
+
+static void dim2_transfer_madr(u32 val)
+{
+	dimcb_io_write(&g.dim2->MADR, val);
+
+	/* wait for transfer completion */
+	while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1)
+		continue;
+
+	dimcb_io_write(&g.dim2->MCTL, 0);   /* clear transfer complete */
+}
+
+static void dim2_clear_dbr(u16 addr, u16 size)
+{
+	enum { MADR_TB_BIT = 30, MADR_WNR_BIT = 31 };
+
+	u16 const end_addr = addr + size;
+	u32 const cmd = bit_mask(MADR_WNR_BIT) | bit_mask(MADR_TB_BIT);
+
+	dimcb_io_write(&g.dim2->MCTL, 0);   /* clear transfer complete */
+	dimcb_io_write(&g.dim2->MDAT0, 0);
+
+	for (; addr < end_addr; addr++)
+		dim2_transfer_madr(cmd | addr);
+}
+
+static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx)
+{
+	dim2_transfer_madr(ctr_addr);
+
+	return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx);
+}
+
+static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value)
+{
+	enum { MADR_WNR_BIT = 31 };
+
+	dimcb_io_write(&g.dim2->MCTL, 0);   /* clear transfer complete */
+
+	if (mask[0] != 0)
+		dimcb_io_write(&g.dim2->MDAT0, value[0]);
+	if (mask[1] != 0)
+		dimcb_io_write(&g.dim2->MDAT1, value[1]);
+	if (mask[2] != 0)
+		dimcb_io_write(&g.dim2->MDAT2, value[2]);
+	if (mask[3] != 0)
+		dimcb_io_write(&g.dim2->MDAT3, value[3]);
+
+	dimcb_io_write(&g.dim2->MDWE0, mask[0]);
+	dimcb_io_write(&g.dim2->MDWE1, mask[1]);
+	dimcb_io_write(&g.dim2->MDWE2, mask[2]);
+	dimcb_io_write(&g.dim2->MDWE3, mask[3]);
+
+	dim2_transfer_madr(bit_mask(MADR_WNR_BIT) | ctr_addr);
+}
+
+static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value)
+{
+	u32 const mask[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+
+	dim2_write_ctr_mask(ctr_addr, mask, value);
+}
+
+static inline void dim2_clear_ctr(u32 ctr_addr)
+{
+	u32 const value[4] = { 0, 0, 0, 0 };
+
+	dim2_write_ctr(ctr_addr, value);
+}
+
+static void dim2_configure_cat(u8 cat_base, u8 ch_addr, u8 ch_type,
+			       bool read_not_write)
+{
+	bool isoc_fce = ch_type == CAT_CT_VAL_ISOC;
+	bool sync_mfe = ch_type == CAT_CT_VAL_SYNC;
+	u16 const cat =
+		(read_not_write << CAT_RNW_BIT) |
+		(ch_type << CAT_CT_SHIFT) |
+		(ch_addr << CAT_CL_SHIFT) |
+		(isoc_fce << CAT_FCE_BIT) |
+		(sync_mfe << CAT_MFE_BIT) |
+		(false << CAT_MT_BIT) |
+		(true << CAT_CE_BIT);
+	u8 const ctr_addr = cat_base + ch_addr / 8;
+	u8 const idx = (ch_addr % 8) / 2;
+	u8 const shift = (ch_addr % 2) * 16;
+	u32 mask[4] = { 0, 0, 0, 0 };
+	u32 value[4] = { 0, 0, 0, 0 };
+
+	mask[idx] = (u32)0xFFFF << shift;
+	value[idx] = cat << shift;
+	dim2_write_ctr_mask(ctr_addr, mask, value);
+}
+
+static void dim2_clear_cat(u8 cat_base, u8 ch_addr)
+{
+	u8 const ctr_addr = cat_base + ch_addr / 8;
+	u8 const idx = (ch_addr % 8) / 2;
+	u8 const shift = (ch_addr % 2) * 16;
+	u32 mask[4] = { 0, 0, 0, 0 };
+	u32 value[4] = { 0, 0, 0, 0 };
+
+	mask[idx] = (u32)0xFFFF << shift;
+	dim2_write_ctr_mask(ctr_addr, mask, value);
+}
+
+static void dim2_configure_cdt(u8 ch_addr, u16 dbr_address, u16 hw_buffer_size,
+			       u16 packet_length)
+{
+	u32 cdt[4] = { 0, 0, 0, 0 };
+
+	if (packet_length)
+		cdt[1] = ((packet_length - 1) << CDT1_BS_ISOC_SHIFT);
+
+	cdt[3] =
+		((hw_buffer_size - 1) << CDT3_BD_SHIFT) |
+		(dbr_address << CDT3_BA_SHIFT);
+	dim2_write_ctr(CDT + ch_addr, cdt);
+}
+
+static u16 dim2_rpc(u8 ch_addr)
+{
+	u32 cdt0 = dim2_read_ctr(CDT + ch_addr, 0);
+
+	return (cdt0 >> CDT0_RPC_SHIFT) & CDT0_RPC_MASK;
+}
+
+static void dim2_clear_cdt(u8 ch_addr)
+{
+	u32 cdt[4] = { 0, 0, 0, 0 };
+
+	dim2_write_ctr(CDT + ch_addr, cdt);
+}
+
+static void dim2_configure_adt(u8 ch_addr)
+{
+	u32 adt[4] = { 0, 0, 0, 0 };
+
+	adt[0] =
+		(true << ADT0_CE_BIT) |
+		(true << ADT0_LE_BIT) |
+		(0 << ADT0_PG_BIT);
+
+	dim2_write_ctr(ADT + ch_addr, adt);
+}
+
+static void dim2_clear_adt(u8 ch_addr)
+{
+	u32 adt[4] = { 0, 0, 0, 0 };
+
+	dim2_write_ctr(ADT + ch_addr, adt);
+}
+
+static void dim2_start_ctrl_async(u8 ch_addr, u8 idx, u32 buf_addr,
+				  u16 buffer_size)
+{
+	u8 const shift = idx * 16;
+
+	u32 mask[4] = { 0, 0, 0, 0 };
+	u32 adt[4] = { 0, 0, 0, 0 };
+
+	mask[1] =
+		bit_mask(ADT1_PS_BIT + shift) |
+		bit_mask(ADT1_RDY_BIT + shift) |
+		(ADT1_CTRL_ASYNC_BD_MASK << (ADT1_BD_SHIFT + shift));
+	adt[1] =
+		(true << (ADT1_PS_BIT + shift)) |
+		(true << (ADT1_RDY_BIT + shift)) |
+		((buffer_size - 1) << (ADT1_BD_SHIFT + shift));
+
+	mask[idx + 2] = 0xFFFFFFFF;
+	adt[idx + 2] = buf_addr;
+
+	dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
+}
+
+static void dim2_start_isoc_sync(u8 ch_addr, u8 idx, u32 buf_addr,
+				 u16 buffer_size)
+{
+	u8 const shift = idx * 16;
+
+	u32 mask[4] = { 0, 0, 0, 0 };
+	u32 adt[4] = { 0, 0, 0, 0 };
+
+	mask[1] =
+		bit_mask(ADT1_RDY_BIT + shift) |
+		(ADT1_ISOC_SYNC_BD_MASK << (ADT1_BD_SHIFT + shift));
+	adt[1] =
+		(true << (ADT1_RDY_BIT + shift)) |
+		((buffer_size - 1) << (ADT1_BD_SHIFT + shift));
+
+	mask[idx + 2] = 0xFFFFFFFF;
+	adt[idx + 2] = buf_addr;
+
+	dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
+}
+
+static void dim2_clear_ctram(void)
+{
+	u32 ctr_addr;
+
+	for (ctr_addr = 0; ctr_addr < 0x90; ctr_addr++)
+		dim2_clear_ctr(ctr_addr);
+}
+
+static void dim2_configure_channel(
+	u8 ch_addr, u8 type, u8 is_tx, u16 dbr_address, u16 hw_buffer_size,
+	u16 packet_length)
+{
+	dim2_configure_cdt(ch_addr, dbr_address, hw_buffer_size, packet_length);
+	dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0);
+
+	dim2_configure_adt(ch_addr);
+	dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1);
+
+	/* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */
+	dimcb_io_write(&g.dim2->ACMR0,
+		       dimcb_io_read(&g.dim2->ACMR0) | bit_mask(ch_addr));
+}
+
+static void dim2_clear_channel(u8 ch_addr)
+{
+	/* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */
+	dimcb_io_write(&g.dim2->ACMR0,
+		       dimcb_io_read(&g.dim2->ACMR0) & ~bit_mask(ch_addr));
+
+	dim2_clear_cat(AHB_CAT, ch_addr);
+	dim2_clear_adt(ch_addr);
+
+	dim2_clear_cat(MLB_CAT, ch_addr);
+	dim2_clear_cdt(ch_addr);
+
+	/* clear channel status bit */
+	dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr));
+}
+
+/* -------------------------------------------------------------------------- */
+/* trace async tx dbr fill state */
+
+static inline u16 norm_pc(u16 pc)
+{
+	return pc & CDT0_RPC_MASK;
+}
+
+static void dbrcnt_init(u8 ch_addr, u16 dbr_size)
+{
+	g.atx_dbr.rest_size = dbr_size;
+	g.atx_dbr.rpc = dim2_rpc(ch_addr);
+	g.atx_dbr.wpc = g.atx_dbr.rpc;
+}
+
+static void dbrcnt_enq(int buf_sz)
+{
+	g.atx_dbr.rest_size -= buf_sz;
+	g.atx_dbr.sz_queue[norm_pc(g.atx_dbr.wpc)] = buf_sz;
+	g.atx_dbr.wpc++;
+}
+
+u16 dim_dbr_space(struct dim_channel *ch)
+{
+	u16 cur_rpc;
+	struct async_tx_dbr *dbr = &g.atx_dbr;
+
+	if (ch->addr != dbr->ch_addr)
+		return 0xFFFF;
+
+	cur_rpc = dim2_rpc(ch->addr);
+
+	while (norm_pc(dbr->rpc) != cur_rpc) {
+		dbr->rest_size += dbr->sz_queue[norm_pc(dbr->rpc)];
+		dbr->rpc++;
+	}
+
+	if ((u16)(dbr->wpc - dbr->rpc) >= CDT0_RPC_MASK)
+		return 0;
+
+	return dbr->rest_size;
+}
+
+/* -------------------------------------------------------------------------- */
+/* channel state helpers */
+
+static void state_init(struct int_ch_state *state)
+{
+	state->request_counter = 0;
+	state->service_counter = 0;
+
+	state->idx1 = 0;
+	state->idx2 = 0;
+	state->level = 0;
+}
+
+/* -------------------------------------------------------------------------- */
+/* macro helper functions */
+
+static inline bool check_channel_address(u32 ch_address)
+{
+	return ch_address > 0 && (ch_address % 2) == 0 &&
+	       (ch_address / 2) <= (u32)CAT_CL_MASK;
+}
+
+static inline bool check_packet_length(u32 packet_length)
+{
+	u16 const max_size = ((u16)CDT3_BD_ISOC_MASK + 1u) / ISOC_DBR_FACTOR;
+
+	if (packet_length <= 0)
+		return false; /* too small */
+
+	if (packet_length > max_size)
+		return false; /* too big */
+
+	if (packet_length - 1u > (u32)CDT1_BS_ISOC_MASK)
+		return false; /* too big */
+
+	return true;
+}
+
+static inline bool check_bytes_per_frame(u32 bytes_per_frame)
+{
+	u16 const bd_factor = g.fcnt + 2;
+	u16 const max_size = ((u16)CDT3_BD_MASK + 1u) >> bd_factor;
+
+	if (bytes_per_frame <= 0)
+		return false; /* too small */
+
+	if (bytes_per_frame > max_size)
+		return false; /* too big */
+
+	return true;
+}
+
+static inline u16 norm_ctrl_async_buffer_size(u16 buf_size)
+{
+	u16 const max_size = (u16)ADT1_CTRL_ASYNC_BD_MASK + 1u;
+
+	if (buf_size > max_size)
+		return max_size;
+
+	return buf_size;
+}
+
+static inline u16 norm_isoc_buffer_size(u16 buf_size, u16 packet_length)
+{
+	u16 n;
+	u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u;
+
+	if (buf_size > max_size)
+		buf_size = max_size;
+
+	n = buf_size / packet_length;
+
+	if (n < 2u)
+		return 0; /* too small buffer for given packet_length */
+
+	return packet_length * n;
+}
+
+static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame)
+{
+	u16 n;
+	u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u;
+	u32 const unit = bytes_per_frame << g.fcnt;
+
+	if (buf_size > max_size)
+		buf_size = max_size;
+
+	n = buf_size / unit;
+
+	if (n < 1u)
+		return 0; /* too small buffer for given bytes_per_frame */
+
+	return unit * n;
+}
+
+static void dim2_cleanup(void)
+{
+	/* disable MediaLB */
+	dimcb_io_write(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT);
+
+	dim2_clear_ctram();
+
+	/* disable mlb_int interrupt */
+	dimcb_io_write(&g.dim2->MIEN, 0);
+
+	/* clear status for all dma channels */
+	dimcb_io_write(&g.dim2->ACSR0, 0xFFFFFFFF);
+	dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF);
+
+	/* mask interrupts for all channels */
+	dimcb_io_write(&g.dim2->ACMR0, 0);
+	dimcb_io_write(&g.dim2->ACMR1, 0);
+}
+
+static void dim2_initialize(bool enable_6pin, u8 mlb_clock)
+{
+	dim2_cleanup();
+
+	/* configure and enable MediaLB */
+	dimcb_io_write(&g.dim2->MLBC0,
+		       enable_6pin << MLBC0_MLBPEN_BIT |
+		       mlb_clock << MLBC0_MLBCLK_SHIFT |
+		       g.fcnt << MLBC0_FCNT_SHIFT |
+		       true << MLBC0_MLBEN_BIT);
+
+	/* activate all HBI channels */
+	dimcb_io_write(&g.dim2->HCMR0, 0xFFFFFFFF);
+	dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF);
+
+	/* enable HBI */
+	dimcb_io_write(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT));
+
+	/* configure DMA */
+	dimcb_io_write(&g.dim2->ACTL,
+		       ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT |
+		       true << ACTL_SCE_BIT);
+}
+
+static bool dim2_is_mlb_locked(void)
+{
+	u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT);
+	u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) |
+			  bit_mask(MLBC1_LOCKERR_BIT);
+	u32 const c1 = dimcb_io_read(&g.dim2->MLBC1);
+	u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT;
+
+	dimcb_io_write(&g.dim2->MLBC1, c1 & nda_mask);
+	return (dimcb_io_read(&g.dim2->MLBC1) & mask1) == 0 &&
+	       (dimcb_io_read(&g.dim2->MLBC0) & mask0) != 0;
+}
+
+/* -------------------------------------------------------------------------- */
+/* channel help routines */
+
+static inline bool service_channel(u8 ch_addr, u8 idx)
+{
+	u8 const shift = idx * 16;
+	u32 const adt1 = dim2_read_ctr(ADT + ch_addr, 1);
+	u32 mask[4] = { 0, 0, 0, 0 };
+	u32 adt_w[4] = { 0, 0, 0, 0 };
+
+	if (((adt1 >> (ADT1_DNE_BIT + shift)) & 1) == 0)
+		return false;
+
+	mask[1] =
+		bit_mask(ADT1_DNE_BIT + shift) |
+		bit_mask(ADT1_ERR_BIT + shift) |
+		bit_mask(ADT1_RDY_BIT + shift);
+	dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w);
+
+	/* clear channel status bit */
+	dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr));
+
+	return true;
+}
+
+/* -------------------------------------------------------------------------- */
+/* channel init routines */
+
+static void isoc_init(struct dim_channel *ch, u8 ch_addr, u16 packet_length)
+{
+	state_init(&ch->state);
+
+	ch->addr = ch_addr;
+
+	ch->packet_length = packet_length;
+	ch->bytes_per_frame = 0;
+	ch->done_sw_buffers_number = 0;
+}
+
+static void sync_init(struct dim_channel *ch, u8 ch_addr, u16 bytes_per_frame)
+{
+	state_init(&ch->state);
+
+	ch->addr = ch_addr;
+
+	ch->packet_length = 0;
+	ch->bytes_per_frame = bytes_per_frame;
+	ch->done_sw_buffers_number = 0;
+}
+
+static void channel_init(struct dim_channel *ch, u8 ch_addr)
+{
+	state_init(&ch->state);
+
+	ch->addr = ch_addr;
+
+	ch->packet_length = 0;
+	ch->bytes_per_frame = 0;
+	ch->done_sw_buffers_number = 0;
+}
+
+/* returns true if channel interrupt state is cleared */
+static bool channel_service_interrupt(struct dim_channel *ch)
+{
+	struct int_ch_state *const state = &ch->state;
+
+	if (!service_channel(ch->addr, state->idx2))
+		return false;
+
+	state->idx2 ^= 1;
+	state->request_counter++;
+	return true;
+}
+
+static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size)
+{
+	struct int_ch_state *const state = &ch->state;
+
+	if (buf_size <= 0)
+		return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad buffer size");
+
+	if (ch->packet_length == 0 && ch->bytes_per_frame == 0 &&
+	    buf_size != norm_ctrl_async_buffer_size(buf_size))
+		return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
+				    "Bad control/async buffer size");
+
+	if (ch->packet_length &&
+	    buf_size != norm_isoc_buffer_size(buf_size, ch->packet_length))
+		return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
+				    "Bad isochronous buffer size");
+
+	if (ch->bytes_per_frame &&
+	    buf_size != norm_sync_buffer_size(buf_size, ch->bytes_per_frame))
+		return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
+				    "Bad synchronous buffer size");
+
+	if (state->level >= 2u)
+		return dim_on_error(DIM_ERR_OVERFLOW, "Channel overflow");
+
+	++state->level;
+
+	if (ch->addr == g.atx_dbr.ch_addr)
+		dbrcnt_enq(buf_size);
+
+	if (ch->packet_length || ch->bytes_per_frame)
+		dim2_start_isoc_sync(ch->addr, state->idx1, buf_addr, buf_size);
+	else
+		dim2_start_ctrl_async(ch->addr, state->idx1, buf_addr,
+				      buf_size);
+	state->idx1 ^= 1;
+
+	return true;
+}
+
+static u8 channel_service(struct dim_channel *ch)
+{
+	struct int_ch_state *const state = &ch->state;
+
+	if (state->service_counter != state->request_counter) {
+		state->service_counter++;
+		if (state->level == 0)
+			return DIM_ERR_UNDERFLOW;
+
+		--state->level;
+		ch->done_sw_buffers_number++;
+	}
+
+	return DIM_NO_ERROR;
+}
+
+static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number)
+{
+	if (buffers_number > ch->done_sw_buffers_number)
+		return dim_on_error(DIM_ERR_UNDERFLOW, "Channel underflow");
+
+	ch->done_sw_buffers_number -= buffers_number;
+	return true;
+}
+
+/* -------------------------------------------------------------------------- */
+/* API */
+
+u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock,
+	       u32 fcnt)
+{
+	g.dim_is_initialized = false;
+
+	if (!dim_base_address)
+		return DIM_INIT_ERR_DIM_ADDR;
+
+	/* MediaLB clock: 0 - 256 fs, 1 - 512 fs, 2 - 1024 fs, 3 - 2048 fs */
+	/* MediaLB clock: 4 - 3072 fs, 5 - 4096 fs, 6 - 6144 fs, 7 - 8192 fs */
+	if (mlb_clock >= 8)
+		return DIM_INIT_ERR_MLB_CLOCK;
+
+	if (fcnt > MLBC0_FCNT_MAX_VAL)
+		return DIM_INIT_ERR_MLB_CLOCK;
+
+	g.dim2 = dim_base_address;
+	g.fcnt = fcnt;
+	g.dbr_map[0] = 0;
+	g.dbr_map[1] = 0;
+
+	dim2_initialize(mlb_clock >= 3, mlb_clock);
+
+	g.dim_is_initialized = true;
+
+	return DIM_NO_ERROR;
+}
+
+void dim_shutdown(void)
+{
+	g.dim_is_initialized = false;
+	dim2_cleanup();
+}
+
+bool dim_get_lock_state(void)
+{
+	return dim2_is_mlb_locked();
+}
+
+static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx,
+			  u16 ch_address, u16 hw_buffer_size)
+{
+	if (!g.dim_is_initialized || !ch)
+		return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+	if (!check_channel_address(ch_address))
+		return DIM_INIT_ERR_CHANNEL_ADDRESS;
+
+	ch->dbr_size = ROUND_UP_TO(hw_buffer_size, DBR_BLOCK_SIZE);
+	ch->dbr_addr = alloc_dbr(ch->dbr_size);
+	if (ch->dbr_addr >= DBR_SIZE)
+		return DIM_INIT_ERR_OUT_OF_MEMORY;
+
+	channel_init(ch, ch_address / 2);
+
+	dim2_configure_channel(ch->addr, type, is_tx,
+			       ch->dbr_addr, ch->dbr_size, 0);
+
+	return DIM_NO_ERROR;
+}
+
+void dim_service_mlb_int_irq(void)
+{
+	dimcb_io_write(&g.dim2->MS0, 0);
+	dimcb_io_write(&g.dim2->MS1, 0);
+}
+
+u16 dim_norm_ctrl_async_buffer_size(u16 buf_size)
+{
+	return norm_ctrl_async_buffer_size(buf_size);
+}
+
+/**
+ * Retrieves maximal possible correct buffer size for isochronous data type
+ * conform to given packet length and not bigger than given buffer size.
+ *
+ * Returns non-zero correct buffer size or zero by error.
+ */
+u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length)
+{
+	if (!check_packet_length(packet_length))
+		return 0;
+
+	return norm_isoc_buffer_size(buf_size, packet_length);
+}
+
+/**
+ * Retrieves maximal possible correct buffer size for synchronous data type
+ * conform to given bytes per frame and not bigger than given buffer size.
+ *
+ * Returns non-zero correct buffer size or zero by error.
+ */
+u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame)
+{
+	if (!check_bytes_per_frame(bytes_per_frame))
+		return 0;
+
+	return norm_sync_buffer_size(buf_size, bytes_per_frame);
+}
+
+u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+		    u16 max_buffer_size)
+{
+	return init_ctrl_async(ch, CAT_CT_VAL_CONTROL, is_tx, ch_address,
+			       max_buffer_size);
+}
+
+u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+		  u16 max_buffer_size)
+{
+	u8 ret = init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address,
+				 max_buffer_size);
+
+	if (is_tx && !g.atx_dbr.ch_addr) {
+		g.atx_dbr.ch_addr = ch->addr;
+		dbrcnt_init(ch->addr, ch->dbr_size);
+		dimcb_io_write(&g.dim2->MIEN, bit_mask(20));
+	}
+
+	return ret;
+}
+
+u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+		 u16 packet_length)
+{
+	if (!g.dim_is_initialized || !ch)
+		return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+	if (!check_channel_address(ch_address))
+		return DIM_INIT_ERR_CHANNEL_ADDRESS;
+
+	if (!check_packet_length(packet_length))
+		return DIM_ERR_BAD_CONFIG;
+
+	ch->dbr_size = packet_length * ISOC_DBR_FACTOR;
+	ch->dbr_addr = alloc_dbr(ch->dbr_size);
+	if (ch->dbr_addr >= DBR_SIZE)
+		return DIM_INIT_ERR_OUT_OF_MEMORY;
+
+	isoc_init(ch, ch_address / 2, packet_length);
+
+	dim2_configure_channel(ch->addr, CAT_CT_VAL_ISOC, is_tx, ch->dbr_addr,
+			       ch->dbr_size, packet_length);
+
+	return DIM_NO_ERROR;
+}
+
+u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+		 u16 bytes_per_frame)
+{
+	u16 bd_factor = g.fcnt + 2;
+
+	if (!g.dim_is_initialized || !ch)
+		return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+	if (!check_channel_address(ch_address))
+		return DIM_INIT_ERR_CHANNEL_ADDRESS;
+
+	if (!check_bytes_per_frame(bytes_per_frame))
+		return DIM_ERR_BAD_CONFIG;
+
+	ch->dbr_size = bytes_per_frame << bd_factor;
+	ch->dbr_addr = alloc_dbr(ch->dbr_size);
+	if (ch->dbr_addr >= DBR_SIZE)
+		return DIM_INIT_ERR_OUT_OF_MEMORY;
+
+	sync_init(ch, ch_address / 2, bytes_per_frame);
+
+	dim2_clear_dbr(ch->dbr_addr, ch->dbr_size);
+	dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx,
+			       ch->dbr_addr, ch->dbr_size, 0);
+
+	return DIM_NO_ERROR;
+}
+
+u8 dim_destroy_channel(struct dim_channel *ch)
+{
+	if (!g.dim_is_initialized || !ch)
+		return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+	if (ch->addr == g.atx_dbr.ch_addr) {
+		dimcb_io_write(&g.dim2->MIEN, 0);
+		g.atx_dbr.ch_addr = 0;
+	}
+
+	dim2_clear_channel(ch->addr);
+	if (ch->dbr_addr < DBR_SIZE)
+		free_dbr(ch->dbr_addr, ch->dbr_size);
+	ch->dbr_addr = DBR_SIZE;
+
+	return DIM_NO_ERROR;
+}
+
+void dim_service_ahb_int_irq(struct dim_channel *const *channels)
+{
+	bool state_changed;
+
+	if (!g.dim_is_initialized) {
+		dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
+			     "DIM is not initialized");
+		return;
+	}
+
+	if (!channels) {
+		dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channels");
+		return;
+	}
+
+	/*
+	 * Use while-loop and a flag to make sure the age is changed back at
+	 * least once, otherwise the interrupt may never come if CPU generates
+	 * interrupt on changing age.
+	 * This cycle runs not more than number of channels, because
+	 * channel_service_interrupt() routine doesn't start the channel again.
+	 */
+	do {
+		struct dim_channel *const *ch = channels;
+
+		state_changed = false;
+
+		while (*ch) {
+			state_changed |= channel_service_interrupt(*ch);
+			++ch;
+		}
+	} while (state_changed);
+}
+
+u8 dim_service_channel(struct dim_channel *ch)
+{
+	if (!g.dim_is_initialized || !ch)
+		return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+	return channel_service(ch);
+}
+
+struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch,
+					     struct dim_ch_state_t *state_ptr)
+{
+	if (!ch || !state_ptr)
+		return NULL;
+
+	state_ptr->ready = ch->state.level < 2;
+	state_ptr->done_buffers = ch->done_sw_buffers_number;
+
+	return state_ptr;
+}
+
+bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr,
+			u16 buffer_size)
+{
+	if (!ch)
+		return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
+				    "Bad channel");
+
+	return channel_start(ch, buffer_addr, buffer_size);
+}
+
+bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number)
+{
+	if (!ch)
+		return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
+				    "Bad channel");
+
+	return channel_detach_buffers(ch, buffers_number);
+}
diff --git a/drivers/staging/most/dim2/hal.h b/drivers/staging/most/dim2/hal.h
new file mode 100644
index 0000000..a08e4a4
--- /dev/null
+++ b/drivers/staging/most/dim2/hal.h
@@ -0,0 +1,112 @@
+/*
+ * hal.h - DIM2 HAL interface
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#ifndef _DIM2_HAL_H
+#define _DIM2_HAL_H
+
+#include <linux/types.h>
+#include "reg.h"
+
+/*
+ * The values below are specified in the hardware specification.
+ * So, they should not be changed until the hardware specification changes.
+ */
+enum mlb_clk_speed {
+	CLK_256FS = 0,
+	CLK_512FS = 1,
+	CLK_1024FS = 2,
+	CLK_2048FS = 3,
+	CLK_3072FS = 4,
+	CLK_4096FS = 5,
+	CLK_6144FS = 6,
+	CLK_8192FS = 7,
+};
+
+struct dim_ch_state_t {
+	bool ready; /* Shows readiness to enqueue next buffer */
+	u16 done_buffers; /* Number of completed buffers */
+};
+
+struct int_ch_state {
+	/* changed only in interrupt context */
+	volatile int request_counter;
+
+	/* changed only in task context */
+	volatile int service_counter;
+
+	u8 idx1;
+	u8 idx2;
+	u8 level; /* [0..2], buffering level */
+};
+
+struct dim_channel {
+	struct int_ch_state state;
+	u8 addr;
+	u16 dbr_addr;
+	u16 dbr_size;
+	u16 packet_length; /*< Isochronous packet length in bytes. */
+	u16 bytes_per_frame; /*< Synchronous bytes per frame. */
+	u16 done_sw_buffers_number; /*< Done software buffers number. */
+};
+
+u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock,
+	       u32 fcnt);
+
+void dim_shutdown(void);
+
+bool dim_get_lock_state(void);
+
+u16 dim_norm_ctrl_async_buffer_size(u16 buf_size);
+
+u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length);
+
+u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame);
+
+u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+		    u16 max_buffer_size);
+
+u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+		  u16 max_buffer_size);
+
+u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+		 u16 packet_length);
+
+u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+		 u16 bytes_per_frame);
+
+u8 dim_destroy_channel(struct dim_channel *ch);
+
+void dim_service_mlb_int_irq(void);
+
+void dim_service_ahb_int_irq(struct dim_channel *const *channels);
+
+u8 dim_service_channel(struct dim_channel *ch);
+
+struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch,
+					     struct dim_ch_state_t *state_ptr);
+
+u16 dim_dbr_space(struct dim_channel *ch);
+
+bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr,
+			u16 buffer_size);
+
+bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number);
+
+u32 dimcb_io_read(u32 __iomem *ptr32);
+
+void dimcb_io_write(u32 __iomem *ptr32, u32 value);
+
+void dimcb_on_error(u8 error_id, const char *error_message);
+
+#endif /* _DIM2_HAL_H */
diff --git a/drivers/staging/most/dim2/reg.h b/drivers/staging/most/dim2/reg.h
new file mode 100644
index 0000000..b0d095c
--- /dev/null
+++ b/drivers/staging/most/dim2/reg.h
@@ -0,0 +1,163 @@
+/*
+ * reg.h - Definitions for registers of DIM2
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#ifndef DIM2_OS62420_H
+#define	DIM2_OS62420_H
+
+#include <linux/types.h>
+
+struct dim2_regs {
+	/* 0x00 */ u32 MLBC0;
+	/* 0x01 */ u32 rsvd0[1];
+	/* 0x02 */ u32 MLBPC0;
+	/* 0x03 */ u32 MS0;
+	/* 0x04 */ u32 rsvd1[1];
+	/* 0x05 */ u32 MS1;
+	/* 0x06 */ u32 rsvd2[2];
+	/* 0x08 */ u32 MSS;
+	/* 0x09 */ u32 MSD;
+	/* 0x0A */ u32 rsvd3[1];
+	/* 0x0B */ u32 MIEN;
+	/* 0x0C */ u32 rsvd4[1];
+	/* 0x0D */ u32 MLBPC2;
+	/* 0x0E */ u32 MLBPC1;
+	/* 0x0F */ u32 MLBC1;
+	/* 0x10 */ u32 rsvd5[0x10];
+	/* 0x20 */ u32 HCTL;
+	/* 0x21 */ u32 rsvd6[1];
+	/* 0x22 */ u32 HCMR0;
+	/* 0x23 */ u32 HCMR1;
+	/* 0x24 */ u32 HCER0;
+	/* 0x25 */ u32 HCER1;
+	/* 0x26 */ u32 HCBR0;
+	/* 0x27 */ u32 HCBR1;
+	/* 0x28 */ u32 rsvd7[8];
+	/* 0x30 */ u32 MDAT0;
+	/* 0x31 */ u32 MDAT1;
+	/* 0x32 */ u32 MDAT2;
+	/* 0x33 */ u32 MDAT3;
+	/* 0x34 */ u32 MDWE0;
+	/* 0x35 */ u32 MDWE1;
+	/* 0x36 */ u32 MDWE2;
+	/* 0x37 */ u32 MDWE3;
+	/* 0x38 */ u32 MCTL;
+	/* 0x39 */ u32 MADR;
+	/* 0x3A */ u32 rsvd8[0xB6];
+	/* 0xF0 */ u32 ACTL;
+	/* 0xF1 */ u32 rsvd9[3];
+	/* 0xF4 */ u32 ACSR0;
+	/* 0xF5 */ u32 ACSR1;
+	/* 0xF6 */ u32 ACMR0;
+	/* 0xF7 */ u32 ACMR1;
+};
+
+#define DIM2_MASK(n)  (~((~(u32)0) << (n)))
+
+enum {
+	MLBC0_MLBLK_BIT = 7,
+
+	MLBC0_MLBPEN_BIT = 5,
+
+	MLBC0_MLBCLK_SHIFT = 2,
+	MLBC0_MLBCLK_VAL_256FS = 0,
+	MLBC0_MLBCLK_VAL_512FS = 1,
+	MLBC0_MLBCLK_VAL_1024FS = 2,
+	MLBC0_MLBCLK_VAL_2048FS = 3,
+
+	MLBC0_FCNT_SHIFT = 15,
+	MLBC0_FCNT_MASK = 7,
+	MLBC0_FCNT_MAX_VAL = 6,
+
+	MLBC0_MLBEN_BIT = 0,
+
+	MIEN_CTX_BREAK_BIT = 29,
+	MIEN_CTX_PE_BIT = 28,
+	MIEN_CTX_DONE_BIT = 27,
+
+	MIEN_CRX_BREAK_BIT = 26,
+	MIEN_CRX_PE_BIT = 25,
+	MIEN_CRX_DONE_BIT = 24,
+
+	MIEN_ATX_BREAK_BIT = 22,
+	MIEN_ATX_PE_BIT = 21,
+	MIEN_ATX_DONE_BIT = 20,
+
+	MIEN_ARX_BREAK_BIT = 19,
+	MIEN_ARX_PE_BIT = 18,
+	MIEN_ARX_DONE_BIT = 17,
+
+	MIEN_SYNC_PE_BIT = 16,
+
+	MIEN_ISOC_BUFO_BIT = 1,
+	MIEN_ISOC_PE_BIT = 0,
+
+	MLBC1_NDA_SHIFT = 8,
+	MLBC1_NDA_MASK = 0xFF,
+
+	MLBC1_CLKMERR_BIT = 7,
+	MLBC1_LOCKERR_BIT = 6,
+
+	ACTL_DMA_MODE_BIT = 2,
+	ACTL_DMA_MODE_VAL_DMA_MODE_0 = 0,
+	ACTL_DMA_MODE_VAL_DMA_MODE_1 = 1,
+	ACTL_SCE_BIT = 0,
+
+	HCTL_EN_BIT = 15
+};
+
+enum {
+	CDT0_RPC_SHIFT = 16 + 11,
+	CDT0_RPC_MASK = DIM2_MASK(5),
+
+	CDT1_BS_ISOC_SHIFT = 0,
+	CDT1_BS_ISOC_MASK = DIM2_MASK(9),
+
+	CDT3_BD_SHIFT = 0,
+	CDT3_BD_MASK = DIM2_MASK(12),
+	CDT3_BD_ISOC_MASK = DIM2_MASK(13),
+	CDT3_BA_SHIFT = 16,
+
+	ADT0_CE_BIT = 15,
+	ADT0_LE_BIT = 14,
+	ADT0_PG_BIT = 13,
+
+	ADT1_RDY_BIT = 15,
+	ADT1_DNE_BIT = 14,
+	ADT1_ERR_BIT = 13,
+	ADT1_PS_BIT = 12,
+	ADT1_MEP_BIT = 11,
+	ADT1_BD_SHIFT = 0,
+	ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11),
+	ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13),
+
+	CAT_FCE_BIT = 14,
+	CAT_MFE_BIT = 14,
+
+	CAT_MT_BIT = 13,
+
+	CAT_RNW_BIT = 12,
+
+	CAT_CE_BIT = 11,
+
+	CAT_CT_SHIFT = 8,
+	CAT_CT_VAL_SYNC = 0,
+	CAT_CT_VAL_CONTROL = 1,
+	CAT_CT_VAL_ASYNC = 2,
+	CAT_CT_VAL_ISOC = 3,
+
+	CAT_CL_SHIFT = 0,
+	CAT_CL_MASK = DIM2_MASK(6)
+};
+
+#endif	/* DIM2_OS62420_H */
diff --git a/drivers/staging/most/dim2/sysfs.c b/drivers/staging/most/dim2/sysfs.c
new file mode 100644
index 0000000..1331cf0
--- /dev/null
+++ b/drivers/staging/most/dim2/sysfs.c
@@ -0,0 +1,115 @@
+/*
+ * sysfs.c - MediaLB sysfs information
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include "sysfs.h"
+
+struct bus_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct medialb_bus *bus, char *buf);
+	ssize_t (*store)(struct medialb_bus *bus, const char *buf,
+			 size_t count);
+};
+
+static ssize_t state_show(struct medialb_bus *bus, char *buf)
+{
+	bool state = dim2_sysfs_get_state_cb();
+
+	return sprintf(buf, "%s\n", state ? "locked" : "");
+}
+
+static struct bus_attr state_attr = __ATTR_RO(state);
+
+static struct attribute *bus_default_attrs[] = {
+	&state_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group bus_attr_group = {
+	.attrs = bus_default_attrs,
+};
+
+static void bus_kobj_release(struct kobject *kobj)
+{
+}
+
+static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr,
+				  char *buf)
+{
+	struct medialb_bus *bus =
+		container_of(kobj, struct medialb_bus, kobj_group);
+	struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
+
+	if (!xattr->show)
+		return -EIO;
+
+	return xattr->show(bus, buf);
+}
+
+static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr,
+				   const char *buf, size_t count)
+{
+	struct medialb_bus *bus =
+		container_of(kobj, struct medialb_bus, kobj_group);
+	struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
+
+	if (!xattr->store)
+		return -EIO;
+
+	return xattr->store(bus, buf, count);
+}
+
+static struct sysfs_ops const bus_kobj_sysfs_ops = {
+	.show = bus_kobj_attr_show,
+	.store = bus_kobj_attr_store,
+};
+
+static struct kobj_type bus_ktype = {
+	.release = bus_kobj_release,
+	.sysfs_ops = &bus_kobj_sysfs_ops,
+};
+
+int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj)
+{
+	int err;
+
+	kobject_init(&bus->kobj_group, &bus_ktype);
+	err = kobject_add(&bus->kobj_group, parent_kobj, "bus");
+	if (err) {
+		pr_err("kobject_add() failed: %d\n", err);
+		goto err_kobject_add;
+	}
+
+	err = sysfs_create_group(&bus->kobj_group, &bus_attr_group);
+	if (err) {
+		pr_err("sysfs_create_group() failed: %d\n", err);
+		goto err_create_group;
+	}
+
+	return 0;
+
+err_create_group:
+	kobject_put(&bus->kobj_group);
+
+err_kobject_add:
+	return err;
+}
+
+void dim2_sysfs_destroy(struct medialb_bus *bus)
+{
+	kobject_put(&bus->kobj_group);
+}
diff --git a/drivers/staging/most/dim2/sysfs.h b/drivers/staging/most/dim2/sysfs.h
new file mode 100644
index 0000000..236de47
--- /dev/null
+++ b/drivers/staging/most/dim2/sysfs.h
@@ -0,0 +1,36 @@
+/*
+ * sysfs.h - MediaLB sysfs information
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
+
+#ifndef DIM2_SYSFS_H
+#define	DIM2_SYSFS_H
+
+#include <linux/kobject.h>
+
+struct medialb_bus {
+	struct kobject kobj_group;
+};
+
+struct dim2_hdm;
+
+int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj);
+void dim2_sysfs_destroy(struct medialb_bus *bus);
+
+/*
+ * callback,
+ * must deliver MediaLB state as true if locked or false if unlocked
+ */
+bool dim2_sysfs_get_state_cb(void);
+
+#endif	/* DIM2_SYSFS_H */
diff --git a/drivers/staging/most/hdm-dim2/Kconfig b/drivers/staging/most/hdm-dim2/Kconfig
deleted file mode 100644
index 663bfeb..0000000
--- a/drivers/staging/most/hdm-dim2/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# MediaLB configuration
-#
-
-config HDM_DIM2
-	tristate "DIM2 HDM"
-	depends on HAS_IOMEM
-
-	---help---
-	  Say Y here if you want to connect via MediaLB to network transceiver.
-	  This device driver is platform dependent and needs an additional
-	  platform driver to be installed. For more information contact
-	  maintainer of this driver.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called hdm_dim2.
diff --git a/drivers/staging/most/hdm-dim2/Makefile b/drivers/staging/most/hdm-dim2/Makefile
deleted file mode 100644
index 6bbee87..0000000
--- a/drivers/staging/most/hdm-dim2/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-obj-$(CONFIG_HDM_DIM2) += hdm_dim2.o
-
-hdm_dim2-objs := dim2_hdm.o dim2_hal.o dim2_sysfs.o
-ccflags-y += -Idrivers/staging/most/mostcore/
-ccflags-y += -Idrivers/staging/most/aim-network/
diff --git a/drivers/staging/most/hdm-dim2/dim2_errors.h b/drivers/staging/most/hdm-dim2/dim2_errors.h
deleted file mode 100644
index 66343ba..0000000
--- a/drivers/staging/most/hdm-dim2/dim2_errors.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * dim2_errors.h - Definitions of errors for DIM2 HAL API
- * (MediaLB, Device Interface Macro IP, OS62420)
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#ifndef _MOST_DIM_ERRORS_H
-#define _MOST_DIM_ERRORS_H
-
-/**
- * MOST DIM errors.
- */
-enum dim_errors_t {
-	/** Not an error */
-	DIM_NO_ERROR = 0,
-
-	/** Bad base address for DIM2 IP */
-	DIM_INIT_ERR_DIM_ADDR = 0x10,
-
-	/**< Bad MediaLB clock */
-	DIM_INIT_ERR_MLB_CLOCK,
-
-	/** Bad channel address */
-	DIM_INIT_ERR_CHANNEL_ADDRESS,
-
-	/** Out of DBR memory */
-	DIM_INIT_ERR_OUT_OF_MEMORY,
-
-	/** DIM API is called while DIM is not initialized successfully */
-	DIM_ERR_DRIVER_NOT_INITIALIZED = 0x20,
-
-	/**
-	 * Configuration does not respect hardware limitations
-	 * for isochronous or synchronous channels
-	 */
-	DIM_ERR_BAD_CONFIG,
-
-	/**
-	 * Buffer size does not respect hardware limitations
-	 * for isochronous or synchronous channels
-	 */
-	DIM_ERR_BAD_BUFFER_SIZE,
-
-	DIM_ERR_UNDERFLOW,
-
-	DIM_ERR_OVERFLOW,
-};
-
-#endif /* _MOST_DIM_ERRORS_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c
deleted file mode 100644
index 9148464..0000000
--- a/drivers/staging/most/hdm-dim2/dim2_hal.c
+++ /dev/null
@@ -1,985 +0,0 @@
-/*
- * dim2_hal.c - DIM2 HAL implementation
- * (MediaLB, Device Interface Macro IP, OS62420)
- *
- * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
-
-#include "dim2_hal.h"
-#include "dim2_errors.h"
-#include "dim2_reg.h"
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-
-/*
- * Size factor for isochronous DBR buffer.
- * Minimal value is 3.
- */
-#define ISOC_DBR_FACTOR 3u
-
-/*
- * Number of 32-bit units for DBR map.
- *
- * 1: block size is 512, max allocation is 16K
- * 2: block size is 256, max allocation is 8K
- * 4: block size is 128, max allocation is 4K
- * 8: block size is 64, max allocation is 2K
- *
- * Min allocated space is block size.
- * Max possible allocated space is 32 blocks.
- */
-#define DBR_MAP_SIZE 2
-
-/* -------------------------------------------------------------------------- */
-/* not configurable area */
-
-#define CDT 0x00
-#define ADT 0x40
-#define MLB_CAT 0x80
-#define AHB_CAT 0x88
-
-#define DBR_SIZE  (16 * 1024) /* specified by IP */
-#define DBR_BLOCK_SIZE  (DBR_SIZE / 32 / DBR_MAP_SIZE)
-
-#define ROUND_UP_TO(x, d)  (DIV_ROUND_UP(x, (d)) * (d))
-
-/* -------------------------------------------------------------------------- */
-/* generic helper functions and macros */
-
-static inline u32 bit_mask(u8 position)
-{
-	return (u32)1 << position;
-}
-
-static inline bool dim_on_error(u8 error_id, const char *error_message)
-{
-	dimcb_on_error(error_id, error_message);
-	return false;
-}
-
-/* -------------------------------------------------------------------------- */
-/* types and local variables */
-
-struct async_tx_dbr {
-	u8 ch_addr;
-	u16 rpc;
-	u16 wpc;
-	u16 rest_size;
-	u16 sz_queue[CDT0_RPC_MASK + 1];
-};
-
-struct lld_global_vars_t {
-	bool dim_is_initialized;
-	bool mcm_is_initialized;
-	struct dim2_regs __iomem *dim2; /* DIM2 core base address */
-	struct async_tx_dbr atx_dbr;
-	u32 fcnt;
-	u32 dbr_map[DBR_MAP_SIZE];
-};
-
-static struct lld_global_vars_t g = { false };
-
-/* -------------------------------------------------------------------------- */
-
-static int dbr_get_mask_size(u16 size)
-{
-	int i;
-
-	for (i = 0; i < 6; i++)
-		if (size <= (DBR_BLOCK_SIZE << i))
-			return 1 << i;
-	return 0;
-}
-
-/**
- * Allocates DBR memory.
- * @param size Allocating memory size.
- * @return Offset in DBR memory by success or DBR_SIZE if out of memory.
- */
-static int alloc_dbr(u16 size)
-{
-	int mask_size;
-	int i, block_idx = 0;
-
-	if (size <= 0)
-		return DBR_SIZE; /* out of memory */
-
-	mask_size = dbr_get_mask_size(size);
-	if (mask_size == 0)
-		return DBR_SIZE; /* out of memory */
-
-	for (i = 0; i < DBR_MAP_SIZE; i++) {
-		u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE);
-		u32 mask = ~((~(u32)0) << blocks);
-
-		do {
-			if ((g.dbr_map[i] & mask) == 0) {
-				g.dbr_map[i] |= mask;
-				return block_idx * DBR_BLOCK_SIZE;
-			}
-			block_idx += mask_size;
-			/* do shift left with 2 steps in case mask_size == 32 */
-			mask <<= mask_size - 1;
-		} while ((mask <<= 1) != 0);
-	}
-
-	return DBR_SIZE; /* out of memory */
-}
-
-static void free_dbr(int offs, int size)
-{
-	int block_idx = offs / DBR_BLOCK_SIZE;
-	u32 const blocks = DIV_ROUND_UP(size, DBR_BLOCK_SIZE);
-	u32 mask = ~((~(u32)0) << blocks);
-
-	mask <<= block_idx % 32;
-	g.dbr_map[block_idx / 32] &= ~mask;
-}
-
-/* -------------------------------------------------------------------------- */
-
-static void dim2_transfer_madr(u32 val)
-{
-	dimcb_io_write(&g.dim2->MADR, val);
-
-	/* wait for transfer completion */
-	while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1)
-		continue;
-
-	dimcb_io_write(&g.dim2->MCTL, 0);   /* clear transfer complete */
-}
-
-static void dim2_clear_dbr(u16 addr, u16 size)
-{
-	enum { MADR_TB_BIT = 30, MADR_WNR_BIT = 31 };
-
-	u16 const end_addr = addr + size;
-	u32 const cmd = bit_mask(MADR_WNR_BIT) | bit_mask(MADR_TB_BIT);
-
-	dimcb_io_write(&g.dim2->MCTL, 0);   /* clear transfer complete */
-	dimcb_io_write(&g.dim2->MDAT0, 0);
-
-	for (; addr < end_addr; addr++)
-		dim2_transfer_madr(cmd | addr);
-}
-
-static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx)
-{
-	dim2_transfer_madr(ctr_addr);
-
-	return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx);
-}
-
-static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value)
-{
-	enum { MADR_WNR_BIT = 31 };
-
-	dimcb_io_write(&g.dim2->MCTL, 0);   /* clear transfer complete */
-
-	if (mask[0] != 0)
-		dimcb_io_write(&g.dim2->MDAT0, value[0]);
-	if (mask[1] != 0)
-		dimcb_io_write(&g.dim2->MDAT1, value[1]);
-	if (mask[2] != 0)
-		dimcb_io_write(&g.dim2->MDAT2, value[2]);
-	if (mask[3] != 0)
-		dimcb_io_write(&g.dim2->MDAT3, value[3]);
-
-	dimcb_io_write(&g.dim2->MDWE0, mask[0]);
-	dimcb_io_write(&g.dim2->MDWE1, mask[1]);
-	dimcb_io_write(&g.dim2->MDWE2, mask[2]);
-	dimcb_io_write(&g.dim2->MDWE3, mask[3]);
-
-	dim2_transfer_madr(bit_mask(MADR_WNR_BIT) | ctr_addr);
-}
-
-static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value)
-{
-	u32 const mask[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
-
-	dim2_write_ctr_mask(ctr_addr, mask, value);
-}
-
-static inline void dim2_clear_ctr(u32 ctr_addr)
-{
-	u32 const value[4] = { 0, 0, 0, 0 };
-
-	dim2_write_ctr(ctr_addr, value);
-}
-
-static void dim2_configure_cat(u8 cat_base, u8 ch_addr, u8 ch_type,
-			       bool read_not_write)
-{
-	bool isoc_fce = ch_type == CAT_CT_VAL_ISOC;
-	bool sync_mfe = ch_type == CAT_CT_VAL_SYNC;
-	u16 const cat =
-		(read_not_write << CAT_RNW_BIT) |
-		(ch_type << CAT_CT_SHIFT) |
-		(ch_addr << CAT_CL_SHIFT) |
-		(isoc_fce << CAT_FCE_BIT) |
-		(sync_mfe << CAT_MFE_BIT) |
-		(false << CAT_MT_BIT) |
-		(true << CAT_CE_BIT);
-	u8 const ctr_addr = cat_base + ch_addr / 8;
-	u8 const idx = (ch_addr % 8) / 2;
-	u8 const shift = (ch_addr % 2) * 16;
-	u32 mask[4] = { 0, 0, 0, 0 };
-	u32 value[4] = { 0, 0, 0, 0 };
-
-	mask[idx] = (u32)0xFFFF << shift;
-	value[idx] = cat << shift;
-	dim2_write_ctr_mask(ctr_addr, mask, value);
-}
-
-static void dim2_clear_cat(u8 cat_base, u8 ch_addr)
-{
-	u8 const ctr_addr = cat_base + ch_addr / 8;
-	u8 const idx = (ch_addr % 8) / 2;
-	u8 const shift = (ch_addr % 2) * 16;
-	u32 mask[4] = { 0, 0, 0, 0 };
-	u32 value[4] = { 0, 0, 0, 0 };
-
-	mask[idx] = (u32)0xFFFF << shift;
-	dim2_write_ctr_mask(ctr_addr, mask, value);
-}
-
-static void dim2_configure_cdt(u8 ch_addr, u16 dbr_address, u16 hw_buffer_size,
-			       u16 packet_length)
-{
-	u32 cdt[4] = { 0, 0, 0, 0 };
-
-	if (packet_length)
-		cdt[1] = ((packet_length - 1) << CDT1_BS_ISOC_SHIFT);
-
-	cdt[3] =
-		((hw_buffer_size - 1) << CDT3_BD_SHIFT) |
-		(dbr_address << CDT3_BA_SHIFT);
-	dim2_write_ctr(CDT + ch_addr, cdt);
-}
-
-static u16 dim2_rpc(u8 ch_addr)
-{
-	u32 cdt0 = dim2_read_ctr(CDT + ch_addr, 0);
-
-	return (cdt0 >> CDT0_RPC_SHIFT) & CDT0_RPC_MASK;
-}
-
-static void dim2_clear_cdt(u8 ch_addr)
-{
-	u32 cdt[4] = { 0, 0, 0, 0 };
-
-	dim2_write_ctr(CDT + ch_addr, cdt);
-}
-
-static void dim2_configure_adt(u8 ch_addr)
-{
-	u32 adt[4] = { 0, 0, 0, 0 };
-
-	adt[0] =
-		(true << ADT0_CE_BIT) |
-		(true << ADT0_LE_BIT) |
-		(0 << ADT0_PG_BIT);
-
-	dim2_write_ctr(ADT + ch_addr, adt);
-}
-
-static void dim2_clear_adt(u8 ch_addr)
-{
-	u32 adt[4] = { 0, 0, 0, 0 };
-
-	dim2_write_ctr(ADT + ch_addr, adt);
-}
-
-static void dim2_start_ctrl_async(u8 ch_addr, u8 idx, u32 buf_addr,
-				  u16 buffer_size)
-{
-	u8 const shift = idx * 16;
-
-	u32 mask[4] = { 0, 0, 0, 0 };
-	u32 adt[4] = { 0, 0, 0, 0 };
-
-	mask[1] =
-		bit_mask(ADT1_PS_BIT + shift) |
-		bit_mask(ADT1_RDY_BIT + shift) |
-		(ADT1_CTRL_ASYNC_BD_MASK << (ADT1_BD_SHIFT + shift));
-	adt[1] =
-		(true << (ADT1_PS_BIT + shift)) |
-		(true << (ADT1_RDY_BIT + shift)) |
-		((buffer_size - 1) << (ADT1_BD_SHIFT + shift));
-
-	mask[idx + 2] = 0xFFFFFFFF;
-	adt[idx + 2] = buf_addr;
-
-	dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
-}
-
-static void dim2_start_isoc_sync(u8 ch_addr, u8 idx, u32 buf_addr,
-				 u16 buffer_size)
-{
-	u8 const shift = idx * 16;
-
-	u32 mask[4] = { 0, 0, 0, 0 };
-	u32 adt[4] = { 0, 0, 0, 0 };
-
-	mask[1] =
-		bit_mask(ADT1_RDY_BIT + shift) |
-		(ADT1_ISOC_SYNC_BD_MASK << (ADT1_BD_SHIFT + shift));
-	adt[1] =
-		(true << (ADT1_RDY_BIT + shift)) |
-		((buffer_size - 1) << (ADT1_BD_SHIFT + shift));
-
-	mask[idx + 2] = 0xFFFFFFFF;
-	adt[idx + 2] = buf_addr;
-
-	dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
-}
-
-static void dim2_clear_ctram(void)
-{
-	u32 ctr_addr;
-
-	for (ctr_addr = 0; ctr_addr < 0x90; ctr_addr++)
-		dim2_clear_ctr(ctr_addr);
-}
-
-static void dim2_configure_channel(
-	u8 ch_addr, u8 type, u8 is_tx, u16 dbr_address, u16 hw_buffer_size,
-	u16 packet_length)
-{
-	dim2_configure_cdt(ch_addr, dbr_address, hw_buffer_size, packet_length);
-	dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0);
-
-	dim2_configure_adt(ch_addr);
-	dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1);
-
-	/* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */
-	dimcb_io_write(&g.dim2->ACMR0,
-		       dimcb_io_read(&g.dim2->ACMR0) | bit_mask(ch_addr));
-}
-
-static void dim2_clear_channel(u8 ch_addr)
-{
-	/* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */
-	dimcb_io_write(&g.dim2->ACMR0,
-		       dimcb_io_read(&g.dim2->ACMR0) & ~bit_mask(ch_addr));
-
-	dim2_clear_cat(AHB_CAT, ch_addr);
-	dim2_clear_adt(ch_addr);
-
-	dim2_clear_cat(MLB_CAT, ch_addr);
-	dim2_clear_cdt(ch_addr);
-
-	/* clear channel status bit */
-	dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr));
-}
-
-/* -------------------------------------------------------------------------- */
-/* trace async tx dbr fill state */
-
-static inline u16 norm_pc(u16 pc)
-{
-	return pc & CDT0_RPC_MASK;
-}
-
-static void dbrcnt_init(u8 ch_addr, u16 dbr_size)
-{
-	g.atx_dbr.rest_size = dbr_size;
-	g.atx_dbr.rpc = dim2_rpc(ch_addr);
-	g.atx_dbr.wpc = g.atx_dbr.rpc;
-}
-
-static void dbrcnt_enq(int buf_sz)
-{
-	g.atx_dbr.rest_size -= buf_sz;
-	g.atx_dbr.sz_queue[norm_pc(g.atx_dbr.wpc)] = buf_sz;
-	g.atx_dbr.wpc++;
-}
-
-u16 dim_dbr_space(struct dim_channel *ch)
-{
-	u16 cur_rpc;
-	struct async_tx_dbr *dbr = &g.atx_dbr;
-
-	if (ch->addr != dbr->ch_addr)
-		return 0xFFFF;
-
-	cur_rpc = dim2_rpc(ch->addr);
-
-	while (norm_pc(dbr->rpc) != cur_rpc) {
-		dbr->rest_size += dbr->sz_queue[norm_pc(dbr->rpc)];
-		dbr->rpc++;
-	}
-
-	if ((u16)(dbr->wpc - dbr->rpc) >= CDT0_RPC_MASK)
-		return 0;
-
-	return dbr->rest_size;
-}
-
-/* -------------------------------------------------------------------------- */
-/* channel state helpers */
-
-static void state_init(struct int_ch_state *state)
-{
-	state->request_counter = 0;
-	state->service_counter = 0;
-
-	state->idx1 = 0;
-	state->idx2 = 0;
-	state->level = 0;
-}
-
-/* -------------------------------------------------------------------------- */
-/* macro helper functions */
-
-static inline bool check_channel_address(u32 ch_address)
-{
-	return ch_address > 0 && (ch_address % 2) == 0 &&
-	       (ch_address / 2) <= (u32)CAT_CL_MASK;
-}
-
-static inline bool check_packet_length(u32 packet_length)
-{
-	u16 const max_size = ((u16)CDT3_BD_ISOC_MASK + 1u) / ISOC_DBR_FACTOR;
-
-	if (packet_length <= 0)
-		return false; /* too small */
-
-	if (packet_length > max_size)
-		return false; /* too big */
-
-	if (packet_length - 1u > (u32)CDT1_BS_ISOC_MASK)
-		return false; /* too big */
-
-	return true;
-}
-
-static inline bool check_bytes_per_frame(u32 bytes_per_frame)
-{
-	u16 const bd_factor = g.fcnt + 2;
-	u16 const max_size = ((u16)CDT3_BD_MASK + 1u) >> bd_factor;
-
-	if (bytes_per_frame <= 0)
-		return false; /* too small */
-
-	if (bytes_per_frame > max_size)
-		return false; /* too big */
-
-	return true;
-}
-
-static inline u16 norm_ctrl_async_buffer_size(u16 buf_size)
-{
-	u16 const max_size = (u16)ADT1_CTRL_ASYNC_BD_MASK + 1u;
-
-	if (buf_size > max_size)
-		return max_size;
-
-	return buf_size;
-}
-
-static inline u16 norm_isoc_buffer_size(u16 buf_size, u16 packet_length)
-{
-	u16 n;
-	u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u;
-
-	if (buf_size > max_size)
-		buf_size = max_size;
-
-	n = buf_size / packet_length;
-
-	if (n < 2u)
-		return 0; /* too small buffer for given packet_length */
-
-	return packet_length * n;
-}
-
-static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame)
-{
-	u16 n;
-	u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u;
-	u32 const unit = bytes_per_frame << g.fcnt;
-
-	if (buf_size > max_size)
-		buf_size = max_size;
-
-	n = buf_size / unit;
-
-	if (n < 1u)
-		return 0; /* too small buffer for given bytes_per_frame */
-
-	return unit * n;
-}
-
-static void dim2_cleanup(void)
-{
-	/* disable MediaLB */
-	dimcb_io_write(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT);
-
-	dim2_clear_ctram();
-
-	/* disable mlb_int interrupt */
-	dimcb_io_write(&g.dim2->MIEN, 0);
-
-	/* clear status for all dma channels */
-	dimcb_io_write(&g.dim2->ACSR0, 0xFFFFFFFF);
-	dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF);
-
-	/* mask interrupts for all channels */
-	dimcb_io_write(&g.dim2->ACMR0, 0);
-	dimcb_io_write(&g.dim2->ACMR1, 0);
-}
-
-static void dim2_initialize(bool enable_6pin, u8 mlb_clock)
-{
-	dim2_cleanup();
-
-	/* configure and enable MediaLB */
-	dimcb_io_write(&g.dim2->MLBC0,
-		       enable_6pin << MLBC0_MLBPEN_BIT |
-		       mlb_clock << MLBC0_MLBCLK_SHIFT |
-		       g.fcnt << MLBC0_FCNT_SHIFT |
-		       true << MLBC0_MLBEN_BIT);
-
-	/* activate all HBI channels */
-	dimcb_io_write(&g.dim2->HCMR0, 0xFFFFFFFF);
-	dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF);
-
-	/* enable HBI */
-	dimcb_io_write(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT));
-
-	/* configure DMA */
-	dimcb_io_write(&g.dim2->ACTL,
-		       ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT |
-		       true << ACTL_SCE_BIT);
-}
-
-static bool dim2_is_mlb_locked(void)
-{
-	u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT);
-	u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) |
-			  bit_mask(MLBC1_LOCKERR_BIT);
-	u32 const c1 = dimcb_io_read(&g.dim2->MLBC1);
-	u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT;
-
-	dimcb_io_write(&g.dim2->MLBC1, c1 & nda_mask);
-	return (dimcb_io_read(&g.dim2->MLBC1) & mask1) == 0 &&
-	       (dimcb_io_read(&g.dim2->MLBC0) & mask0) != 0;
-}
-
-/* -------------------------------------------------------------------------- */
-/* channel help routines */
-
-static inline bool service_channel(u8 ch_addr, u8 idx)
-{
-	u8 const shift = idx * 16;
-	u32 const adt1 = dim2_read_ctr(ADT + ch_addr, 1);
-	u32 mask[4] = { 0, 0, 0, 0 };
-	u32 adt_w[4] = { 0, 0, 0, 0 };
-
-	if (((adt1 >> (ADT1_DNE_BIT + shift)) & 1) == 0)
-		return false;
-
-	mask[1] =
-		bit_mask(ADT1_DNE_BIT + shift) |
-		bit_mask(ADT1_ERR_BIT + shift) |
-		bit_mask(ADT1_RDY_BIT + shift);
-	dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w);
-
-	/* clear channel status bit */
-	dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr));
-
-	return true;
-}
-
-/* -------------------------------------------------------------------------- */
-/* channel init routines */
-
-static void isoc_init(struct dim_channel *ch, u8 ch_addr, u16 packet_length)
-{
-	state_init(&ch->state);
-
-	ch->addr = ch_addr;
-
-	ch->packet_length = packet_length;
-	ch->bytes_per_frame = 0;
-	ch->done_sw_buffers_number = 0;
-}
-
-static void sync_init(struct dim_channel *ch, u8 ch_addr, u16 bytes_per_frame)
-{
-	state_init(&ch->state);
-
-	ch->addr = ch_addr;
-
-	ch->packet_length = 0;
-	ch->bytes_per_frame = bytes_per_frame;
-	ch->done_sw_buffers_number = 0;
-}
-
-static void channel_init(struct dim_channel *ch, u8 ch_addr)
-{
-	state_init(&ch->state);
-
-	ch->addr = ch_addr;
-
-	ch->packet_length = 0;
-	ch->bytes_per_frame = 0;
-	ch->done_sw_buffers_number = 0;
-}
-
-/* returns true if channel interrupt state is cleared */
-static bool channel_service_interrupt(struct dim_channel *ch)
-{
-	struct int_ch_state *const state = &ch->state;
-
-	if (!service_channel(ch->addr, state->idx2))
-		return false;
-
-	state->idx2 ^= 1;
-	state->request_counter++;
-	return true;
-}
-
-static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size)
-{
-	struct int_ch_state *const state = &ch->state;
-
-	if (buf_size <= 0)
-		return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad buffer size");
-
-	if (ch->packet_length == 0 && ch->bytes_per_frame == 0 &&
-	    buf_size != norm_ctrl_async_buffer_size(buf_size))
-		return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
-				    "Bad control/async buffer size");
-
-	if (ch->packet_length &&
-	    buf_size != norm_isoc_buffer_size(buf_size, ch->packet_length))
-		return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
-				    "Bad isochronous buffer size");
-
-	if (ch->bytes_per_frame &&
-	    buf_size != norm_sync_buffer_size(buf_size, ch->bytes_per_frame))
-		return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
-				    "Bad synchronous buffer size");
-
-	if (state->level >= 2u)
-		return dim_on_error(DIM_ERR_OVERFLOW, "Channel overflow");
-
-	++state->level;
-
-	if (ch->addr == g.atx_dbr.ch_addr)
-		dbrcnt_enq(buf_size);
-
-	if (ch->packet_length || ch->bytes_per_frame)
-		dim2_start_isoc_sync(ch->addr, state->idx1, buf_addr, buf_size);
-	else
-		dim2_start_ctrl_async(ch->addr, state->idx1, buf_addr,
-				      buf_size);
-	state->idx1 ^= 1;
-
-	return true;
-}
-
-static u8 channel_service(struct dim_channel *ch)
-{
-	struct int_ch_state *const state = &ch->state;
-
-	if (state->service_counter != state->request_counter) {
-		state->service_counter++;
-		if (state->level == 0)
-			return DIM_ERR_UNDERFLOW;
-
-		--state->level;
-		ch->done_sw_buffers_number++;
-	}
-
-	return DIM_NO_ERROR;
-}
-
-static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number)
-{
-	if (buffers_number > ch->done_sw_buffers_number)
-		return dim_on_error(DIM_ERR_UNDERFLOW, "Channel underflow");
-
-	ch->done_sw_buffers_number -= buffers_number;
-	return true;
-}
-
-/* -------------------------------------------------------------------------- */
-/* API */
-
-u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock,
-	       u32 fcnt)
-{
-	g.dim_is_initialized = false;
-
-	if (!dim_base_address)
-		return DIM_INIT_ERR_DIM_ADDR;
-
-	/* MediaLB clock: 0 - 256 fs, 1 - 512 fs, 2 - 1024 fs, 3 - 2048 fs */
-	/* MediaLB clock: 4 - 3072 fs, 5 - 4096 fs, 6 - 6144 fs, 7 - 8192 fs */
-	if (mlb_clock >= 8)
-		return DIM_INIT_ERR_MLB_CLOCK;
-
-	if (fcnt > MLBC0_FCNT_MAX_VAL)
-		return DIM_INIT_ERR_MLB_CLOCK;
-
-	g.dim2 = dim_base_address;
-	g.fcnt = fcnt;
-	g.dbr_map[0] = 0;
-	g.dbr_map[1] = 0;
-
-	dim2_initialize(mlb_clock >= 3, mlb_clock);
-
-	g.dim_is_initialized = true;
-
-	return DIM_NO_ERROR;
-}
-
-void dim_shutdown(void)
-{
-	g.dim_is_initialized = false;
-	dim2_cleanup();
-}
-
-bool dim_get_lock_state(void)
-{
-	return dim2_is_mlb_locked();
-}
-
-static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx,
-			  u16 ch_address, u16 hw_buffer_size)
-{
-	if (!g.dim_is_initialized || !ch)
-		return DIM_ERR_DRIVER_NOT_INITIALIZED;
-
-	if (!check_channel_address(ch_address))
-		return DIM_INIT_ERR_CHANNEL_ADDRESS;
-
-	ch->dbr_size = ROUND_UP_TO(hw_buffer_size, DBR_BLOCK_SIZE);
-	ch->dbr_addr = alloc_dbr(ch->dbr_size);
-	if (ch->dbr_addr >= DBR_SIZE)
-		return DIM_INIT_ERR_OUT_OF_MEMORY;
-
-	channel_init(ch, ch_address / 2);
-
-	dim2_configure_channel(ch->addr, type, is_tx,
-			       ch->dbr_addr, ch->dbr_size, 0);
-
-	return DIM_NO_ERROR;
-}
-
-void dim_service_mlb_int_irq(void)
-{
-	dimcb_io_write(&g.dim2->MS0, 0);
-	dimcb_io_write(&g.dim2->MS1, 0);
-}
-
-u16 dim_norm_ctrl_async_buffer_size(u16 buf_size)
-{
-	return norm_ctrl_async_buffer_size(buf_size);
-}
-
-/**
- * Retrieves maximal possible correct buffer size for isochronous data type
- * conform to given packet length and not bigger than given buffer size.
- *
- * Returns non-zero correct buffer size or zero by error.
- */
-u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length)
-{
-	if (!check_packet_length(packet_length))
-		return 0;
-
-	return norm_isoc_buffer_size(buf_size, packet_length);
-}
-
-/**
- * Retrieves maximal possible correct buffer size for synchronous data type
- * conform to given bytes per frame and not bigger than given buffer size.
- *
- * Returns non-zero correct buffer size or zero by error.
- */
-u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame)
-{
-	if (!check_bytes_per_frame(bytes_per_frame))
-		return 0;
-
-	return norm_sync_buffer_size(buf_size, bytes_per_frame);
-}
-
-u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-		    u16 max_buffer_size)
-{
-	return init_ctrl_async(ch, CAT_CT_VAL_CONTROL, is_tx, ch_address,
-			       max_buffer_size);
-}
-
-u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-		  u16 max_buffer_size)
-{
-	u8 ret = init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address,
-				 max_buffer_size);
-
-	if (is_tx && !g.atx_dbr.ch_addr) {
-		g.atx_dbr.ch_addr = ch->addr;
-		dbrcnt_init(ch->addr, ch->dbr_size);
-		dimcb_io_write(&g.dim2->MIEN, bit_mask(20));
-	}
-
-	return ret;
-}
-
-u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-		 u16 packet_length)
-{
-	if (!g.dim_is_initialized || !ch)
-		return DIM_ERR_DRIVER_NOT_INITIALIZED;
-
-	if (!check_channel_address(ch_address))
-		return DIM_INIT_ERR_CHANNEL_ADDRESS;
-
-	if (!check_packet_length(packet_length))
-		return DIM_ERR_BAD_CONFIG;
-
-	ch->dbr_size = packet_length * ISOC_DBR_FACTOR;
-	ch->dbr_addr = alloc_dbr(ch->dbr_size);
-	if (ch->dbr_addr >= DBR_SIZE)
-		return DIM_INIT_ERR_OUT_OF_MEMORY;
-
-	isoc_init(ch, ch_address / 2, packet_length);
-
-	dim2_configure_channel(ch->addr, CAT_CT_VAL_ISOC, is_tx, ch->dbr_addr,
-			       ch->dbr_size, packet_length);
-
-	return DIM_NO_ERROR;
-}
-
-u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-		 u16 bytes_per_frame)
-{
-	u16 bd_factor = g.fcnt + 2;
-
-	if (!g.dim_is_initialized || !ch)
-		return DIM_ERR_DRIVER_NOT_INITIALIZED;
-
-	if (!check_channel_address(ch_address))
-		return DIM_INIT_ERR_CHANNEL_ADDRESS;
-
-	if (!check_bytes_per_frame(bytes_per_frame))
-		return DIM_ERR_BAD_CONFIG;
-
-	ch->dbr_size = bytes_per_frame << bd_factor;
-	ch->dbr_addr = alloc_dbr(ch->dbr_size);
-	if (ch->dbr_addr >= DBR_SIZE)
-		return DIM_INIT_ERR_OUT_OF_MEMORY;
-
-	sync_init(ch, ch_address / 2, bytes_per_frame);
-
-	dim2_clear_dbr(ch->dbr_addr, ch->dbr_size);
-	dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx,
-			       ch->dbr_addr, ch->dbr_size, 0);
-
-	return DIM_NO_ERROR;
-}
-
-u8 dim_destroy_channel(struct dim_channel *ch)
-{
-	if (!g.dim_is_initialized || !ch)
-		return DIM_ERR_DRIVER_NOT_INITIALIZED;
-
-	if (ch->addr == g.atx_dbr.ch_addr) {
-		dimcb_io_write(&g.dim2->MIEN, 0);
-		g.atx_dbr.ch_addr = 0;
-	}
-
-	dim2_clear_channel(ch->addr);
-	if (ch->dbr_addr < DBR_SIZE)
-		free_dbr(ch->dbr_addr, ch->dbr_size);
-	ch->dbr_addr = DBR_SIZE;
-
-	return DIM_NO_ERROR;
-}
-
-void dim_service_ahb_int_irq(struct dim_channel *const *channels)
-{
-	bool state_changed;
-
-	if (!g.dim_is_initialized) {
-		dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
-			     "DIM is not initialized");
-		return;
-	}
-
-	if (!channels) {
-		dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channels");
-		return;
-	}
-
-	/*
-	 * Use while-loop and a flag to make sure the age is changed back at
-	 * least once, otherwise the interrupt may never come if CPU generates
-	 * interrupt on changing age.
-	 * This cycle runs not more than number of channels, because
-	 * channel_service_interrupt() routine doesn't start the channel again.
-	 */
-	do {
-		struct dim_channel *const *ch = channels;
-
-		state_changed = false;
-
-		while (*ch) {
-			state_changed |= channel_service_interrupt(*ch);
-			++ch;
-		}
-	} while (state_changed);
-}
-
-u8 dim_service_channel(struct dim_channel *ch)
-{
-	if (!g.dim_is_initialized || !ch)
-		return DIM_ERR_DRIVER_NOT_INITIALIZED;
-
-	return channel_service(ch);
-}
-
-struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch,
-					     struct dim_ch_state_t *state_ptr)
-{
-	if (!ch || !state_ptr)
-		return NULL;
-
-	state_ptr->ready = ch->state.level < 2;
-	state_ptr->done_buffers = ch->done_sw_buffers_number;
-
-	return state_ptr;
-}
-
-bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr,
-			u16 buffer_size)
-{
-	if (!ch)
-		return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
-				    "Bad channel");
-
-	return channel_start(ch, buffer_addr, buffer_size);
-}
-
-bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number)
-{
-	if (!ch)
-		return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
-				    "Bad channel");
-
-	return channel_detach_buffers(ch, buffers_number);
-}
diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h
deleted file mode 100644
index 6df6ea5..0000000
--- a/drivers/staging/most/hdm-dim2/dim2_hal.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * dim2_hal.h - DIM2 HAL interface
- * (MediaLB, Device Interface Macro IP, OS62420)
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#ifndef _DIM2_HAL_H
-#define _DIM2_HAL_H
-
-#include <linux/types.h>
-#include "dim2_reg.h"
-
-/*
- * The values below are specified in the hardware specification.
- * So, they should not be changed until the hardware specification changes.
- */
-enum mlb_clk_speed {
-	CLK_256FS = 0,
-	CLK_512FS = 1,
-	CLK_1024FS = 2,
-	CLK_2048FS = 3,
-	CLK_3072FS = 4,
-	CLK_4096FS = 5,
-	CLK_6144FS = 6,
-	CLK_8192FS = 7,
-};
-
-struct dim_ch_state_t {
-	bool ready; /* Shows readiness to enqueue next buffer */
-	u16 done_buffers; /* Number of completed buffers */
-};
-
-struct int_ch_state {
-	/* changed only in interrupt context */
-	volatile int request_counter;
-
-	/* changed only in task context */
-	volatile int service_counter;
-
-	u8 idx1;
-	u8 idx2;
-	u8 level; /* [0..2], buffering level */
-};
-
-struct dim_channel {
-	struct int_ch_state state;
-	u8 addr;
-	u16 dbr_addr;
-	u16 dbr_size;
-	u16 packet_length; /*< Isochronous packet length in bytes. */
-	u16 bytes_per_frame; /*< Synchronous bytes per frame. */
-	u16 done_sw_buffers_number; /*< Done software buffers number. */
-};
-
-u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock,
-	       u32 fcnt);
-
-void dim_shutdown(void);
-
-bool dim_get_lock_state(void);
-
-u16 dim_norm_ctrl_async_buffer_size(u16 buf_size);
-
-u16 dim_norm_isoc_buffer_size(u16 buf_size, u16 packet_length);
-
-u16 dim_norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame);
-
-u8 dim_init_control(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-		    u16 max_buffer_size);
-
-u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-		  u16 max_buffer_size);
-
-u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-		 u16 packet_length);
-
-u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
-		 u16 bytes_per_frame);
-
-u8 dim_destroy_channel(struct dim_channel *ch);
-
-void dim_service_mlb_int_irq(void);
-
-void dim_service_ahb_int_irq(struct dim_channel *const *channels);
-
-u8 dim_service_channel(struct dim_channel *ch);
-
-struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch,
-					     struct dim_ch_state_t *state_ptr);
-
-u16 dim_dbr_space(struct dim_channel *ch);
-
-bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr,
-			u16 buffer_size);
-
-bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number);
-
-u32 dimcb_io_read(u32 __iomem *ptr32);
-
-void dimcb_io_write(u32 __iomem *ptr32, u32 value);
-
-void dimcb_on_error(u8 error_id, const char *error_message);
-
-#endif /* _DIM2_HAL_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c
deleted file mode 100644
index df7021c..0000000
--- a/drivers/staging/most/hdm-dim2/dim2_hdm.c
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * dim2_hdm.c - MediaLB DIM2 Hardware Dependent Module
- *
- * Copyright (C) 2015-2016, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/printk.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/dma-mapping.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-
-#include <mostcore.h>
-#include "dim2_hal.h"
-#include "dim2_hdm.h"
-#include "dim2_errors.h"
-#include "dim2_sysfs.h"
-
-#define DMA_CHANNELS (32 - 1)  /* channel 0 is a system channel */
-
-#define MAX_BUFFERS_PACKET      32
-#define MAX_BUFFERS_STREAMING   32
-#define MAX_BUF_SIZE_PACKET     2048
-#define MAX_BUF_SIZE_STREAMING  (8 * 1024)
-
-/* command line parameter to select clock speed */
-static char *clock_speed;
-module_param(clock_speed, charp, 0000);
-MODULE_PARM_DESC(clock_speed, "MediaLB Clock Speed");
-
-/*
- * The parameter representing the number of frames per sub-buffer for
- * synchronous channels.  Valid values: [0 .. 6].
- *
- * The values 0, 1, 2, 3, 4, 5, 6 represent corresponding number of frames per
- * sub-buffer 1, 2, 4, 8, 16, 32, 64.
- */
-static u8 fcnt = 4;  /* (1 << fcnt) frames per subbuffer */
-module_param(fcnt, byte, 0000);
-MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a power of 2");
-
-static DEFINE_SPINLOCK(dim_lock);
-
-static void dim2_tasklet_fn(unsigned long data);
-static DECLARE_TASKLET(dim2_tasklet, dim2_tasklet_fn, 0);
-
-/**
- * struct hdm_channel - private structure to keep channel specific data
- * @is_initialized: identifier to know whether the channel is initialized
- * @ch: HAL specific channel data
- * @pending_list: list to keep MBO's before starting transfer
- * @started_list: list to keep MBO's after starting transfer
- * @direction: channel direction (TX or RX)
- * @data_type: channel data type
- */
-struct hdm_channel {
-	char name[sizeof "caNNN"];
-	bool is_initialized;
-	struct dim_channel ch;
-	struct list_head pending_list;	/* before dim_enqueue_buffer() */
-	struct list_head started_list;	/* after dim_enqueue_buffer() */
-	enum most_channel_direction direction;
-	enum most_channel_data_type data_type;
-};
-
-/**
- * struct dim2_hdm - private structure to keep interface specific data
- * @hch: an array of channel specific data
- * @most_iface: most interface structure
- * @capabilities: an array of channel capability data
- * @io_base: I/O register base address
- * @clk_speed: user selectable (through command line parameter) clock speed
- * @netinfo_task: thread to deliver network status
- * @netinfo_waitq: waitq for the thread to sleep
- * @deliver_netinfo: to identify whether network status received
- * @mac_addrs: INIC mac address
- * @link_state: network link state
- * @atx_idx: index of async tx channel
- */
-struct dim2_hdm {
-	struct hdm_channel hch[DMA_CHANNELS];
-	struct most_channel_capability capabilities[DMA_CHANNELS];
-	struct most_interface most_iface;
-	char name[16 + sizeof "dim2-"];
-	void __iomem *io_base;
-	int clk_speed;
-	struct task_struct *netinfo_task;
-	wait_queue_head_t netinfo_waitq;
-	int deliver_netinfo;
-	unsigned char mac_addrs[6];
-	unsigned char link_state;
-	int atx_idx;
-	struct medialb_bus bus;
-	void (*on_netinfo)(struct most_interface *,
-			   unsigned char, unsigned char *);
-};
-
-#define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface)
-
-/* Macro to identify a network status message */
-#define PACKET_IS_NET_INFO(p)  \
-	(((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \
-	 ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A))
-
-bool dim2_sysfs_get_state_cb(void)
-{
-	bool state;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dim_lock, flags);
-	state = dim_get_lock_state();
-	spin_unlock_irqrestore(&dim_lock, flags);
-
-	return state;
-}
-
-/**
- * dimcb_io_read - callback from HAL to read an I/O register
- * @ptr32: register address
- */
-u32 dimcb_io_read(u32 __iomem *ptr32)
-{
-	return readl(ptr32);
-}
-
-/**
- * dimcb_io_write - callback from HAL to write value to an I/O register
- * @ptr32: register address
- * @value: value to write
- */
-void dimcb_io_write(u32 __iomem *ptr32, u32 value)
-{
-	writel(value, ptr32);
-}
-
-/**
- * dimcb_on_error - callback from HAL to report miscommunication between
- * HDM and HAL
- * @error_id: Error ID
- * @error_message: Error message. Some text in a free format
- */
-void dimcb_on_error(u8 error_id, const char *error_message)
-{
-	pr_err("dimcb_on_error: error_id - %d, error_message - %s\n", error_id,
-	       error_message);
-}
-
-/**
- * startup_dim - initialize the dim2 interface
- * @pdev: platform device
- *
- * Get the value of command line parameter "clock_speed" if given or use the
- * default value, enable the clock and PLL, and initialize the dim2 interface.
- */
-static int startup_dim(struct platform_device *pdev)
-{
-	struct dim2_hdm *dev = platform_get_drvdata(pdev);
-	struct dim2_platform_data *pdata = pdev->dev.platform_data;
-	u8 hal_ret;
-
-	dev->clk_speed = -1;
-
-	if (clock_speed) {
-		if (!strcmp(clock_speed, "256fs"))
-			dev->clk_speed = CLK_256FS;
-		else if (!strcmp(clock_speed, "512fs"))
-			dev->clk_speed = CLK_512FS;
-		else if (!strcmp(clock_speed, "1024fs"))
-			dev->clk_speed = CLK_1024FS;
-		else if (!strcmp(clock_speed, "2048fs"))
-			dev->clk_speed = CLK_2048FS;
-		else if (!strcmp(clock_speed, "3072fs"))
-			dev->clk_speed = CLK_3072FS;
-		else if (!strcmp(clock_speed, "4096fs"))
-			dev->clk_speed = CLK_4096FS;
-		else if (!strcmp(clock_speed, "6144fs"))
-			dev->clk_speed = CLK_6144FS;
-		else if (!strcmp(clock_speed, "8192fs"))
-			dev->clk_speed = CLK_8192FS;
-	}
-
-	if (dev->clk_speed == -1) {
-		pr_info("Bad or missing clock speed parameter, using default value: 3072fs\n");
-		dev->clk_speed = CLK_3072FS;
-	} else {
-		pr_info("Selected clock speed: %s\n", clock_speed);
-	}
-	if (pdata && pdata->init) {
-		int ret = pdata->init(pdata, dev->io_base, dev->clk_speed);
-
-		if (ret)
-			return ret;
-	}
-
-	pr_info("sync: num of frames per sub-buffer: %u\n", fcnt);
-	hal_ret = dim_startup(dev->io_base, dev->clk_speed, fcnt);
-	if (hal_ret != DIM_NO_ERROR) {
-		pr_err("dim_startup failed: %d\n", hal_ret);
-		if (pdata && pdata->destroy)
-			pdata->destroy(pdata);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-/**
- * try_start_dim_transfer - try to transfer a buffer on a channel
- * @hdm_ch: channel specific data
- *
- * Transfer a buffer from pending_list if the channel is ready
- */
-static int try_start_dim_transfer(struct hdm_channel *hdm_ch)
-{
-	u16 buf_size;
-	struct list_head *head = &hdm_ch->pending_list;
-	struct mbo *mbo;
-	unsigned long flags;
-	struct dim_ch_state_t st;
-
-	BUG_ON(!hdm_ch);
-	BUG_ON(!hdm_ch->is_initialized);
-
-	spin_lock_irqsave(&dim_lock, flags);
-	if (list_empty(head)) {
-		spin_unlock_irqrestore(&dim_lock, flags);
-		return -EAGAIN;
-	}
-
-	if (!dim_get_channel_state(&hdm_ch->ch, &st)->ready) {
-		spin_unlock_irqrestore(&dim_lock, flags);
-		return -EAGAIN;
-	}
-
-	mbo = list_first_entry(head, struct mbo, list);
-	buf_size = mbo->buffer_length;
-
-	if (dim_dbr_space(&hdm_ch->ch) < buf_size) {
-		spin_unlock_irqrestore(&dim_lock, flags);
-		return -EAGAIN;
-	}
-
-	BUG_ON(mbo->bus_address == 0);
-	if (!dim_enqueue_buffer(&hdm_ch->ch, mbo->bus_address, buf_size)) {
-		list_del(head->next);
-		spin_unlock_irqrestore(&dim_lock, flags);
-		mbo->processed_length = 0;
-		mbo->status = MBO_E_INVAL;
-		mbo->complete(mbo);
-		return -EFAULT;
-	}
-
-	list_move_tail(head->next, &hdm_ch->started_list);
-	spin_unlock_irqrestore(&dim_lock, flags);
-
-	return 0;
-}
-
-/**
- * deliver_netinfo_thread - thread to deliver network status to mostcore
- * @data: private data
- *
- * Wait for network status and deliver it to mostcore once it is received
- */
-static int deliver_netinfo_thread(void *data)
-{
-	struct dim2_hdm *dev = data;
-
-	while (!kthread_should_stop()) {
-		wait_event_interruptible(dev->netinfo_waitq,
-					 dev->deliver_netinfo ||
-					 kthread_should_stop());
-
-		if (dev->deliver_netinfo) {
-			dev->deliver_netinfo--;
-			if (dev->on_netinfo) {
-				dev->on_netinfo(&dev->most_iface,
-						dev->link_state,
-						dev->mac_addrs);
-			}
-		}
-	}
-
-	return 0;
-}
-
-/**
- * retrieve_netinfo - retrieve network status from received buffer
- * @dev: private data
- * @mbo: received MBO
- *
- * Parse the message in buffer and get node address, link state, MAC address.
- * Wake up a thread to deliver this status to mostcore
- */
-static void retrieve_netinfo(struct dim2_hdm *dev, struct mbo *mbo)
-{
-	u8 *data = mbo->virt_address;
-
-	pr_info("Node Address: 0x%03x\n", (u16)data[16] << 8 | data[17]);
-	dev->link_state = data[18];
-	pr_info("NIState: %d\n", dev->link_state);
-	memcpy(dev->mac_addrs, data + 19, 6);
-	dev->deliver_netinfo++;
-	wake_up_interruptible(&dev->netinfo_waitq);
-}
-
-/**
- * service_done_flag - handle completed buffers
- * @dev: private data
- * @ch_idx: channel index
- *
- * Return back the completed buffers to mostcore, using completion callback
- */
-static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
-{
-	struct hdm_channel *hdm_ch = dev->hch + ch_idx;
-	struct dim_ch_state_t st;
-	struct list_head *head;
-	struct mbo *mbo;
-	int done_buffers;
-	unsigned long flags;
-	u8 *data;
-
-	BUG_ON(!hdm_ch);
-	BUG_ON(!hdm_ch->is_initialized);
-
-	spin_lock_irqsave(&dim_lock, flags);
-
-	done_buffers = dim_get_channel_state(&hdm_ch->ch, &st)->done_buffers;
-	if (!done_buffers) {
-		spin_unlock_irqrestore(&dim_lock, flags);
-		return;
-	}
-
-	if (!dim_detach_buffers(&hdm_ch->ch, done_buffers)) {
-		spin_unlock_irqrestore(&dim_lock, flags);
-		return;
-	}
-	spin_unlock_irqrestore(&dim_lock, flags);
-
-	head = &hdm_ch->started_list;
-
-	while (done_buffers) {
-		spin_lock_irqsave(&dim_lock, flags);
-		if (list_empty(head)) {
-			spin_unlock_irqrestore(&dim_lock, flags);
-			pr_crit("hard error: started_mbo list is empty whereas DIM2 has sent buffers\n");
-			break;
-		}
-
-		mbo = list_first_entry(head, struct mbo, list);
-		list_del(head->next);
-		spin_unlock_irqrestore(&dim_lock, flags);
-
-		data = mbo->virt_address;
-
-		if (hdm_ch->data_type == MOST_CH_ASYNC &&
-		    hdm_ch->direction == MOST_CH_RX &&
-		    PACKET_IS_NET_INFO(data)) {
-			retrieve_netinfo(dev, mbo);
-
-			spin_lock_irqsave(&dim_lock, flags);
-			list_add_tail(&mbo->list, &hdm_ch->pending_list);
-			spin_unlock_irqrestore(&dim_lock, flags);
-		} else {
-			if (hdm_ch->data_type == MOST_CH_CONTROL ||
-			    hdm_ch->data_type == MOST_CH_ASYNC) {
-				u32 const data_size =
-					(u32)data[0] * 256 + data[1] + 2;
-
-				mbo->processed_length =
-					min_t(u32, data_size,
-					      mbo->buffer_length);
-			} else {
-				mbo->processed_length = mbo->buffer_length;
-			}
-			mbo->status = MBO_SUCCESS;
-			mbo->complete(mbo);
-		}
-
-		done_buffers--;
-	}
-}
-
-static struct dim_channel **get_active_channels(struct dim2_hdm *dev,
-						struct dim_channel **buffer)
-{
-	int idx = 0;
-	int ch_idx;
-
-	for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) {
-		if (dev->hch[ch_idx].is_initialized)
-			buffer[idx++] = &dev->hch[ch_idx].ch;
-	}
-	buffer[idx++] = NULL;
-
-	return buffer;
-}
-
-static irqreturn_t dim2_mlb_isr(int irq, void *_dev)
-{
-	struct dim2_hdm *dev = _dev;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dim_lock, flags);
-	dim_service_mlb_int_irq();
-	spin_unlock_irqrestore(&dim_lock, flags);
-
-	if (dev->atx_idx >= 0 && dev->hch[dev->atx_idx].is_initialized)
-		while (!try_start_dim_transfer(dev->hch + dev->atx_idx))
-			continue;
-
-	return IRQ_HANDLED;
-}
-
-/**
- * dim2_tasklet_fn - tasklet function
- * @data: private data
- *
- * Service each initialized channel, if needed
- */
-static void dim2_tasklet_fn(unsigned long data)
-{
-	struct dim2_hdm *dev = (struct dim2_hdm *)data;
-	unsigned long flags;
-	int ch_idx;
-
-	for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) {
-		if (!dev->hch[ch_idx].is_initialized)
-			continue;
-
-		spin_lock_irqsave(&dim_lock, flags);
-		dim_service_channel(&dev->hch[ch_idx].ch);
-		spin_unlock_irqrestore(&dim_lock, flags);
-
-		service_done_flag(dev, ch_idx);
-		while (!try_start_dim_transfer(dev->hch + ch_idx))
-			continue;
-	}
-}
-
-/**
- * dim2_ahb_isr - interrupt service routine
- * @irq: irq number
- * @_dev: private data
- *
- * Acknowledge the interrupt and schedule a tasklet to service channels.
- * Return IRQ_HANDLED.
- */
-static irqreturn_t dim2_ahb_isr(int irq, void *_dev)
-{
-	struct dim2_hdm *dev = _dev;
-	struct dim_channel *buffer[DMA_CHANNELS + 1];
-	unsigned long flags;
-
-	spin_lock_irqsave(&dim_lock, flags);
-	dim_service_ahb_int_irq(get_active_channels(dev, buffer));
-	spin_unlock_irqrestore(&dim_lock, flags);
-
-	dim2_tasklet.data = (unsigned long)dev;
-	tasklet_schedule(&dim2_tasklet);
-	return IRQ_HANDLED;
-}
-
-/**
- * complete_all_mbos - complete MBO's in a list
- * @head: list head
- *
- * Delete all the entries in list and return back MBO's to mostcore using
- * completion call back.
- */
-static void complete_all_mbos(struct list_head *head)
-{
-	unsigned long flags;
-	struct mbo *mbo;
-
-	for (;;) {
-		spin_lock_irqsave(&dim_lock, flags);
-		if (list_empty(head)) {
-			spin_unlock_irqrestore(&dim_lock, flags);
-			break;
-		}
-
-		mbo = list_first_entry(head, struct mbo, list);
-		list_del(head->next);
-		spin_unlock_irqrestore(&dim_lock, flags);
-
-		mbo->processed_length = 0;
-		mbo->status = MBO_E_CLOSE;
-		mbo->complete(mbo);
-	}
-}
-
-/**
- * configure_channel - initialize a channel
- * @iface: interface the channel belongs to
- * @channel: channel to be configured
- * @channel_config: structure that holds the configuration information
- *
- * Receives configuration information from mostcore and initialize
- * the corresponding channel. Return 0 on success, negative on failure.
- */
-static int configure_channel(struct most_interface *most_iface, int ch_idx,
-			     struct most_channel_config *ccfg)
-{
-	struct dim2_hdm *dev = iface_to_hdm(most_iface);
-	bool const is_tx = ccfg->direction == MOST_CH_TX;
-	u16 const sub_size = ccfg->subbuffer_size;
-	u16 const buf_size = ccfg->buffer_size;
-	u16 new_size;
-	unsigned long flags;
-	u8 hal_ret;
-	int const ch_addr = ch_idx * 2 + 2;
-	struct hdm_channel *const hdm_ch = dev->hch + ch_idx;
-
-	BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
-
-	if (hdm_ch->is_initialized)
-		return -EPERM;
-
-	switch (ccfg->data_type) {
-	case MOST_CH_CONTROL:
-		new_size = dim_norm_ctrl_async_buffer_size(buf_size);
-		if (new_size == 0) {
-			pr_err("%s: too small buffer size\n", hdm_ch->name);
-			return -EINVAL;
-		}
-		ccfg->buffer_size = new_size;
-		if (new_size != buf_size)
-			pr_warn("%s: fixed buffer size (%d -> %d)\n",
-				hdm_ch->name, buf_size, new_size);
-		spin_lock_irqsave(&dim_lock, flags);
-		hal_ret = dim_init_control(&hdm_ch->ch, is_tx, ch_addr,
-					   is_tx ? new_size * 2 : new_size);
-		break;
-	case MOST_CH_ASYNC:
-		new_size = dim_norm_ctrl_async_buffer_size(buf_size);
-		if (new_size == 0) {
-			pr_err("%s: too small buffer size\n", hdm_ch->name);
-			return -EINVAL;
-		}
-		ccfg->buffer_size = new_size;
-		if (new_size != buf_size)
-			pr_warn("%s: fixed buffer size (%d -> %d)\n",
-				hdm_ch->name, buf_size, new_size);
-		spin_lock_irqsave(&dim_lock, flags);
-		hal_ret = dim_init_async(&hdm_ch->ch, is_tx, ch_addr,
-					 is_tx ? new_size * 2 : new_size);
-		break;
-	case MOST_CH_ISOC:
-		new_size = dim_norm_isoc_buffer_size(buf_size, sub_size);
-		if (new_size == 0) {
-			pr_err("%s: invalid sub-buffer size or too small buffer size\n",
-			       hdm_ch->name);
-			return -EINVAL;
-		}
-		ccfg->buffer_size = new_size;
-		if (new_size != buf_size)
-			pr_warn("%s: fixed buffer size (%d -> %d)\n",
-				hdm_ch->name, buf_size, new_size);
-		spin_lock_irqsave(&dim_lock, flags);
-		hal_ret = dim_init_isoc(&hdm_ch->ch, is_tx, ch_addr, sub_size);
-		break;
-	case MOST_CH_SYNC:
-		new_size = dim_norm_sync_buffer_size(buf_size, sub_size);
-		if (new_size == 0) {
-			pr_err("%s: invalid sub-buffer size or too small buffer size\n",
-			       hdm_ch->name);
-			return -EINVAL;
-		}
-		ccfg->buffer_size = new_size;
-		if (new_size != buf_size)
-			pr_warn("%s: fixed buffer size (%d -> %d)\n",
-				hdm_ch->name, buf_size, new_size);
-		spin_lock_irqsave(&dim_lock, flags);
-		hal_ret = dim_init_sync(&hdm_ch->ch, is_tx, ch_addr, sub_size);
-		break;
-	default:
-		pr_err("%s: configure failed, bad channel type: %d\n",
-		       hdm_ch->name, ccfg->data_type);
-		return -EINVAL;
-	}
-
-	if (hal_ret != DIM_NO_ERROR) {
-		spin_unlock_irqrestore(&dim_lock, flags);
-		pr_err("%s: configure failed (%d), type: %d, is_tx: %d\n",
-		       hdm_ch->name, hal_ret, ccfg->data_type, (int)is_tx);
-		return -ENODEV;
-	}
-
-	hdm_ch->data_type = ccfg->data_type;
-	hdm_ch->direction = ccfg->direction;
-	hdm_ch->is_initialized = true;
-
-	if (hdm_ch->data_type == MOST_CH_ASYNC &&
-	    hdm_ch->direction == MOST_CH_TX &&
-	    dev->atx_idx < 0)
-		dev->atx_idx = ch_idx;
-
-	spin_unlock_irqrestore(&dim_lock, flags);
-
-	return 0;
-}
-
-/**
- * enqueue - enqueue a buffer for data transfer
- * @iface: intended interface
- * @channel: ID of the channel the buffer is intended for
- * @mbo: pointer to the buffer object
- *
- * Push the buffer into pending_list and try to transfer one buffer from
- * pending_list. Return 0 on success, negative on failure.
- */
-static int enqueue(struct most_interface *most_iface, int ch_idx,
-		   struct mbo *mbo)
-{
-	struct dim2_hdm *dev = iface_to_hdm(most_iface);
-	struct hdm_channel *hdm_ch = dev->hch + ch_idx;
-	unsigned long flags;
-
-	BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
-
-	if (!hdm_ch->is_initialized)
-		return -EPERM;
-
-	if (mbo->bus_address == 0)
-		return -EFAULT;
-
-	spin_lock_irqsave(&dim_lock, flags);
-	list_add_tail(&mbo->list, &hdm_ch->pending_list);
-	spin_unlock_irqrestore(&dim_lock, flags);
-
-	(void)try_start_dim_transfer(hdm_ch);
-
-	return 0;
-}
-
-/**
- * request_netinfo - triggers retrieving of network info
- * @iface: pointer to the interface
- * @channel_id: corresponding channel ID
- *
- * Send a command to INIC which triggers retrieving of network info by means of
- * "Message exchange over MDP/MEP". Return 0 on success, negative on failure.
- */
-static void request_netinfo(struct most_interface *most_iface, int ch_idx,
-			    void (*on_netinfo)(struct most_interface *,
-					       unsigned char, unsigned char *))
-{
-	struct dim2_hdm *dev = iface_to_hdm(most_iface);
-	struct mbo *mbo;
-	u8 *data;
-
-	dev->on_netinfo = on_netinfo;
-	if (!on_netinfo)
-		return;
-
-	if (dev->atx_idx < 0) {
-		pr_err("Async Tx Not initialized\n");
-		return;
-	}
-
-	mbo = most_get_mbo(&dev->most_iface, dev->atx_idx, NULL);
-	if (!mbo)
-		return;
-
-	mbo->buffer_length = 5;
-
-	data = mbo->virt_address;
-
-	data[0] = 0x00; /* PML High byte */
-	data[1] = 0x03; /* PML Low byte */
-	data[2] = 0x02; /* PMHL */
-	data[3] = 0x08; /* FPH */
-	data[4] = 0x40; /* FMF (FIFO cmd msg - Triggers NAOverMDP) */
-
-	most_submit_mbo(mbo);
-}
-
-/**
- * poison_channel - poison buffers of a channel
- * @iface: pointer to the interface the channel to be poisoned belongs to
- * @channel_id: corresponding channel ID
- *
- * Destroy a channel and complete all the buffers in both started_list &
- * pending_list. Return 0 on success, negative on failure.
- */
-static int poison_channel(struct most_interface *most_iface, int ch_idx)
-{
-	struct dim2_hdm *dev = iface_to_hdm(most_iface);
-	struct hdm_channel *hdm_ch = dev->hch + ch_idx;
-	unsigned long flags;
-	u8 hal_ret;
-	int ret = 0;
-
-	BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
-
-	if (!hdm_ch->is_initialized)
-		return -EPERM;
-
-	tasklet_disable(&dim2_tasklet);
-	spin_lock_irqsave(&dim_lock, flags);
-	hal_ret = dim_destroy_channel(&hdm_ch->ch);
-	hdm_ch->is_initialized = false;
-	if (ch_idx == dev->atx_idx)
-		dev->atx_idx = -1;
-	spin_unlock_irqrestore(&dim_lock, flags);
-	tasklet_enable(&dim2_tasklet);
-	if (hal_ret != DIM_NO_ERROR) {
-		pr_err("HAL Failed to close channel %s\n", hdm_ch->name);
-		ret = -EFAULT;
-	}
-
-	complete_all_mbos(&hdm_ch->started_list);
-	complete_all_mbos(&hdm_ch->pending_list);
-
-	return ret;
-}
-
-/*
- * dim2_probe - dim2 probe handler
- * @pdev: platform device structure
- *
- * Register the dim2 interface with mostcore and initialize it.
- * Return 0 on success, negative on failure.
- */
-static int dim2_probe(struct platform_device *pdev)
-{
-	struct dim2_hdm *dev;
-	struct resource *res;
-	int ret, i;
-	struct kobject *kobj;
-	int irq;
-
-	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return -ENOMEM;
-
-	dev->atx_idx = -1;
-
-	platform_set_drvdata(pdev, dev);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	dev->io_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dev->io_base))
-		return PTR_ERR(dev->io_base);
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "failed to get ahb0_int irq: %d\n", irq);
-		return irq;
-	}
-
-	ret = devm_request_irq(&pdev->dev, irq, dim2_ahb_isr, 0,
-			       "dim2_ahb0_int", dev);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to request ahb0_int irq %d\n", irq);
-		return ret;
-	}
-
-	irq = platform_get_irq(pdev, 1);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "failed to get mlb_int irq: %d\n", irq);
-		return irq;
-	}
-
-	ret = devm_request_irq(&pdev->dev, irq, dim2_mlb_isr, 0,
-			       "dim2_mlb_int", dev);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to request mlb_int irq %d\n", irq);
-		return ret;
-	}
-
-	init_waitqueue_head(&dev->netinfo_waitq);
-	dev->deliver_netinfo = 0;
-	dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev,
-					"dim2_netinfo");
-	if (IS_ERR(dev->netinfo_task))
-		return PTR_ERR(dev->netinfo_task);
-
-	for (i = 0; i < DMA_CHANNELS; i++) {
-		struct most_channel_capability *cap = dev->capabilities + i;
-		struct hdm_channel *hdm_ch = dev->hch + i;
-
-		INIT_LIST_HEAD(&hdm_ch->pending_list);
-		INIT_LIST_HEAD(&hdm_ch->started_list);
-		hdm_ch->is_initialized = false;
-		snprintf(hdm_ch->name, sizeof(hdm_ch->name), "ca%d", i * 2 + 2);
-
-		cap->name_suffix = hdm_ch->name;
-		cap->direction = MOST_CH_RX | MOST_CH_TX;
-		cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
-				 MOST_CH_ISOC | MOST_CH_SYNC;
-		cap->num_buffers_packet = MAX_BUFFERS_PACKET;
-		cap->buffer_size_packet = MAX_BUF_SIZE_PACKET;
-		cap->num_buffers_streaming = MAX_BUFFERS_STREAMING;
-		cap->buffer_size_streaming = MAX_BUF_SIZE_STREAMING;
-	}
-
-	{
-		const char *fmt;
-
-		if (sizeof(res->start) == sizeof(long long))
-			fmt = "dim2-%016llx";
-		else if (sizeof(res->start) == sizeof(long))
-			fmt = "dim2-%016lx";
-		else
-			fmt = "dim2-%016x";
-
-		snprintf(dev->name, sizeof(dev->name), fmt, res->start);
-	}
-
-	dev->most_iface.interface = ITYPE_MEDIALB_DIM2;
-	dev->most_iface.description = dev->name;
-	dev->most_iface.num_channels = DMA_CHANNELS;
-	dev->most_iface.channel_vector = dev->capabilities;
-	dev->most_iface.configure = configure_channel;
-	dev->most_iface.enqueue = enqueue;
-	dev->most_iface.poison_channel = poison_channel;
-	dev->most_iface.request_netinfo = request_netinfo;
-
-	kobj = most_register_interface(&dev->most_iface);
-	if (IS_ERR(kobj)) {
-		ret = PTR_ERR(kobj);
-		dev_err(&pdev->dev, "failed to register MOST interface\n");
-		goto err_stop_thread;
-	}
-
-	ret = dim2_sysfs_probe(&dev->bus, kobj);
-	if (ret)
-		goto err_unreg_iface;
-
-	ret = startup_dim(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to initialize DIM2\n");
-		goto err_destroy_bus;
-	}
-
-	return 0;
-
-err_destroy_bus:
-	dim2_sysfs_destroy(&dev->bus);
-err_unreg_iface:
-	most_deregister_interface(&dev->most_iface);
-err_stop_thread:
-	kthread_stop(dev->netinfo_task);
-
-	return ret;
-}
-
-/**
- * dim2_remove - dim2 remove handler
- * @pdev: platform device structure
- *
- * Unregister the interface from mostcore
- */
-static int dim2_remove(struct platform_device *pdev)
-{
-	struct dim2_hdm *dev = platform_get_drvdata(pdev);
-	struct dim2_platform_data *pdata = pdev->dev.platform_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dim_lock, flags);
-	dim_shutdown();
-	spin_unlock_irqrestore(&dim_lock, flags);
-
-	if (pdata && pdata->destroy)
-		pdata->destroy(pdata);
-
-	dim2_sysfs_destroy(&dev->bus);
-	most_deregister_interface(&dev->most_iface);
-	kthread_stop(dev->netinfo_task);
-
-	/*
-	 * break link to local platform_device_id struct
-	 * to prevent crash by unload platform device module
-	 */
-	pdev->id_entry = NULL;
-
-	return 0;
-}
-
-static const struct platform_device_id dim2_id[] = {
-	{ "medialb_dim2" },
-	{ }, /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(platform, dim2_id);
-
-static struct platform_driver dim2_driver = {
-	.probe = dim2_probe,
-	.remove = dim2_remove,
-	.id_table = dim2_id,
-	.driver = {
-		.name = "hdm_dim2",
-	},
-};
-
-module_platform_driver(dim2_driver);
-
-MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
-MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
-MODULE_DESCRIPTION("MediaLB DIM2 Hardware Dependent Module");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.h b/drivers/staging/most/hdm-dim2/dim2_hdm.h
deleted file mode 100644
index 4050e7c..0000000
--- a/drivers/staging/most/hdm-dim2/dim2_hdm.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * dim2_hdm.h - MediaLB DIM2 HDM Header
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#ifndef DIM2_HDM_H
-#define	DIM2_HDM_H
-
-struct device;
-
-/* platform dependent data for dim2 interface */
-struct dim2_platform_data {
-	int (*init)(struct dim2_platform_data *pd, void __iomem *io_base,
-		    int clk_speed);
-	void (*destroy)(struct dim2_platform_data *pd);
-	void *priv;
-};
-
-#endif	/* DIM2_HDM_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h
deleted file mode 100644
index f7d9fbc..0000000
--- a/drivers/staging/most/hdm-dim2/dim2_reg.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * dim2_reg.h - Definitions for registers of DIM2
- * (MediaLB, Device Interface Macro IP, OS62420)
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#ifndef DIM2_OS62420_H
-#define	DIM2_OS62420_H
-
-#include <linux/types.h>
-
-struct dim2_regs {
-	/* 0x00 */ u32 MLBC0;
-	/* 0x01 */ u32 rsvd0[1];
-	/* 0x02 */ u32 MLBPC0;
-	/* 0x03 */ u32 MS0;
-	/* 0x04 */ u32 rsvd1[1];
-	/* 0x05 */ u32 MS1;
-	/* 0x06 */ u32 rsvd2[2];
-	/* 0x08 */ u32 MSS;
-	/* 0x09 */ u32 MSD;
-	/* 0x0A */ u32 rsvd3[1];
-	/* 0x0B */ u32 MIEN;
-	/* 0x0C */ u32 rsvd4[1];
-	/* 0x0D */ u32 MLBPC2;
-	/* 0x0E */ u32 MLBPC1;
-	/* 0x0F */ u32 MLBC1;
-	/* 0x10 */ u32 rsvd5[0x10];
-	/* 0x20 */ u32 HCTL;
-	/* 0x21 */ u32 rsvd6[1];
-	/* 0x22 */ u32 HCMR0;
-	/* 0x23 */ u32 HCMR1;
-	/* 0x24 */ u32 HCER0;
-	/* 0x25 */ u32 HCER1;
-	/* 0x26 */ u32 HCBR0;
-	/* 0x27 */ u32 HCBR1;
-	/* 0x28 */ u32 rsvd7[8];
-	/* 0x30 */ u32 MDAT0;
-	/* 0x31 */ u32 MDAT1;
-	/* 0x32 */ u32 MDAT2;
-	/* 0x33 */ u32 MDAT3;
-	/* 0x34 */ u32 MDWE0;
-	/* 0x35 */ u32 MDWE1;
-	/* 0x36 */ u32 MDWE2;
-	/* 0x37 */ u32 MDWE3;
-	/* 0x38 */ u32 MCTL;
-	/* 0x39 */ u32 MADR;
-	/* 0x3A */ u32 rsvd8[0xB6];
-	/* 0xF0 */ u32 ACTL;
-	/* 0xF1 */ u32 rsvd9[3];
-	/* 0xF4 */ u32 ACSR0;
-	/* 0xF5 */ u32 ACSR1;
-	/* 0xF6 */ u32 ACMR0;
-	/* 0xF7 */ u32 ACMR1;
-};
-
-#define DIM2_MASK(n)  (~((~(u32)0) << (n)))
-
-enum {
-	MLBC0_MLBLK_BIT = 7,
-
-	MLBC0_MLBPEN_BIT = 5,
-
-	MLBC0_MLBCLK_SHIFT = 2,
-	MLBC0_MLBCLK_VAL_256FS = 0,
-	MLBC0_MLBCLK_VAL_512FS = 1,
-	MLBC0_MLBCLK_VAL_1024FS = 2,
-	MLBC0_MLBCLK_VAL_2048FS = 3,
-
-	MLBC0_FCNT_SHIFT = 15,
-	MLBC0_FCNT_MASK = 7,
-	MLBC0_FCNT_MAX_VAL = 6,
-
-	MLBC0_MLBEN_BIT = 0,
-
-	MIEN_CTX_BREAK_BIT = 29,
-	MIEN_CTX_PE_BIT = 28,
-	MIEN_CTX_DONE_BIT = 27,
-
-	MIEN_CRX_BREAK_BIT = 26,
-	MIEN_CRX_PE_BIT = 25,
-	MIEN_CRX_DONE_BIT = 24,
-
-	MIEN_ATX_BREAK_BIT = 22,
-	MIEN_ATX_PE_BIT = 21,
-	MIEN_ATX_DONE_BIT = 20,
-
-	MIEN_ARX_BREAK_BIT = 19,
-	MIEN_ARX_PE_BIT = 18,
-	MIEN_ARX_DONE_BIT = 17,
-
-	MIEN_SYNC_PE_BIT = 16,
-
-	MIEN_ISOC_BUFO_BIT = 1,
-	MIEN_ISOC_PE_BIT = 0,
-
-	MLBC1_NDA_SHIFT = 8,
-	MLBC1_NDA_MASK = 0xFF,
-
-	MLBC1_CLKMERR_BIT = 7,
-	MLBC1_LOCKERR_BIT = 6,
-
-	ACTL_DMA_MODE_BIT = 2,
-	ACTL_DMA_MODE_VAL_DMA_MODE_0 = 0,
-	ACTL_DMA_MODE_VAL_DMA_MODE_1 = 1,
-	ACTL_SCE_BIT = 0,
-
-	HCTL_EN_BIT = 15
-};
-
-enum {
-	CDT0_RPC_SHIFT = 16 + 11,
-	CDT0_RPC_MASK = DIM2_MASK(5),
-
-	CDT1_BS_ISOC_SHIFT = 0,
-	CDT1_BS_ISOC_MASK = DIM2_MASK(9),
-
-	CDT3_BD_SHIFT = 0,
-	CDT3_BD_MASK = DIM2_MASK(12),
-	CDT3_BD_ISOC_MASK = DIM2_MASK(13),
-	CDT3_BA_SHIFT = 16,
-
-	ADT0_CE_BIT = 15,
-	ADT0_LE_BIT = 14,
-	ADT0_PG_BIT = 13,
-
-	ADT1_RDY_BIT = 15,
-	ADT1_DNE_BIT = 14,
-	ADT1_ERR_BIT = 13,
-	ADT1_PS_BIT = 12,
-	ADT1_MEP_BIT = 11,
-	ADT1_BD_SHIFT = 0,
-	ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11),
-	ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13),
-
-	CAT_FCE_BIT = 14,
-	CAT_MFE_BIT = 14,
-
-	CAT_MT_BIT = 13,
-
-	CAT_RNW_BIT = 12,
-
-	CAT_CE_BIT = 11,
-
-	CAT_CT_SHIFT = 8,
-	CAT_CT_VAL_SYNC = 0,
-	CAT_CT_VAL_CONTROL = 1,
-	CAT_CT_VAL_ASYNC = 2,
-	CAT_CT_VAL_ISOC = 3,
-
-	CAT_CL_SHIFT = 0,
-	CAT_CL_MASK = DIM2_MASK(6)
-};
-
-#endif	/* DIM2_OS62420_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.c b/drivers/staging/most/hdm-dim2/dim2_sysfs.c
deleted file mode 100644
index d8b22f9..0000000
--- a/drivers/staging/most/hdm-dim2/dim2_sysfs.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * dim2_sysfs.c - MediaLB sysfs information
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include "dim2_sysfs.h"
-
-struct bus_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct medialb_bus *bus, char *buf);
-	ssize_t (*store)(struct medialb_bus *bus, const char *buf,
-			 size_t count);
-};
-
-static ssize_t state_show(struct medialb_bus *bus, char *buf)
-{
-	bool state = dim2_sysfs_get_state_cb();
-
-	return sprintf(buf, "%s\n", state ? "locked" : "");
-}
-
-static struct bus_attr state_attr = __ATTR_RO(state);
-
-static struct attribute *bus_default_attrs[] = {
-	&state_attr.attr,
-	NULL,
-};
-
-static const struct attribute_group bus_attr_group = {
-	.attrs = bus_default_attrs,
-};
-
-static void bus_kobj_release(struct kobject *kobj)
-{
-}
-
-static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr,
-				  char *buf)
-{
-	struct medialb_bus *bus =
-		container_of(kobj, struct medialb_bus, kobj_group);
-	struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
-
-	if (!xattr->show)
-		return -EIO;
-
-	return xattr->show(bus, buf);
-}
-
-static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr,
-				   const char *buf, size_t count)
-{
-	struct medialb_bus *bus =
-		container_of(kobj, struct medialb_bus, kobj_group);
-	struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
-
-	if (!xattr->store)
-		return -EIO;
-
-	return xattr->store(bus, buf, count);
-}
-
-static struct sysfs_ops const bus_kobj_sysfs_ops = {
-	.show = bus_kobj_attr_show,
-	.store = bus_kobj_attr_store,
-};
-
-static struct kobj_type bus_ktype = {
-	.release = bus_kobj_release,
-	.sysfs_ops = &bus_kobj_sysfs_ops,
-};
-
-int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj)
-{
-	int err;
-
-	kobject_init(&bus->kobj_group, &bus_ktype);
-	err = kobject_add(&bus->kobj_group, parent_kobj, "bus");
-	if (err) {
-		pr_err("kobject_add() failed: %d\n", err);
-		goto err_kobject_add;
-	}
-
-	err = sysfs_create_group(&bus->kobj_group, &bus_attr_group);
-	if (err) {
-		pr_err("sysfs_create_group() failed: %d\n", err);
-		goto err_create_group;
-	}
-
-	return 0;
-
-err_create_group:
-	kobject_put(&bus->kobj_group);
-
-err_kobject_add:
-	return err;
-}
-
-void dim2_sysfs_destroy(struct medialb_bus *bus)
-{
-	kobject_put(&bus->kobj_group);
-}
diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.h b/drivers/staging/most/hdm-dim2/dim2_sysfs.h
deleted file mode 100644
index b71dd02..0000000
--- a/drivers/staging/most/hdm-dim2/dim2_sysfs.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * dim2_sysfs.h - MediaLB sysfs information
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
-
-#ifndef DIM2_SYSFS_H
-#define	DIM2_SYSFS_H
-
-#include <linux/kobject.h>
-
-struct medialb_bus {
-	struct kobject kobj_group;
-};
-
-struct dim2_hdm;
-
-int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj);
-void dim2_sysfs_destroy(struct medialb_bus *bus);
-
-/*
- * callback,
- * must deliver MediaLB state as true if locked or false if unlocked
- */
-bool dim2_sysfs_get_state_cb(void);
-
-#endif	/* DIM2_SYSFS_H */
diff --git a/drivers/staging/most/hdm-i2c/Kconfig b/drivers/staging/most/hdm-i2c/Kconfig
deleted file mode 100644
index 6fd7983..0000000
--- a/drivers/staging/most/hdm-i2c/Kconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# MOST I2C configuration
-#
-
-config HDM_I2C
-	tristate "I2C HDM"
-	depends on I2C
-	---help---
-	  Say Y here if you want to connect via I2C to network tranceiver.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called hdm_i2c.
diff --git a/drivers/staging/most/hdm-i2c/Makefile b/drivers/staging/most/hdm-i2c/Makefile
deleted file mode 100644
index 03a4a59..0000000
--- a/drivers/staging/most/hdm-i2c/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_HDM_I2C) += hdm_i2c.o
-
-ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/hdm-i2c/hdm_i2c.c
deleted file mode 100644
index 2b4de40..0000000
--- a/drivers/staging/most/hdm-i2c/hdm_i2c.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * hdm_i2c.c - Hardware Dependent Module for I2C Interface
- *
- * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-
-#include <mostcore.h>
-
-enum { CH_RX, CH_TX, NUM_CHANNELS };
-
-#define MAX_BUFFERS_CONTROL 32
-#define MAX_BUF_SIZE_CONTROL 256
-
-/**
- * list_first_mbo - get the first mbo from a list
- * @ptr:	the list head to take the mbo from.
- */
-#define list_first_mbo(ptr) \
-	list_first_entry(ptr, struct mbo, list)
-
-/* IRQ / Polling option */
-static bool polling_req;
-module_param(polling_req, bool, 0444);
-MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)");
-
-/* Polling Rate */
-static int scan_rate = 100;
-module_param(scan_rate, int, 0644);
-MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 100");
-
-struct hdm_i2c {
-	bool is_open[NUM_CHANNELS];
-	bool polling_mode;
-	struct most_interface most_iface;
-	struct most_channel_capability capabilities[NUM_CHANNELS];
-	struct i2c_client *client;
-	struct rx {
-		struct delayed_work dwork;
-		wait_queue_head_t waitq;
-		struct list_head list;
-		struct mutex list_mutex;
-	} rx;
-	char name[64];
-};
-
-#define to_hdm(iface) container_of(iface, struct hdm_i2c, most_iface)
-
-/**
- * configure_channel - called from MOST core to configure a channel
- * @iface: interface the channel belongs to
- * @channel: channel to be configured
- * @channel_config: structure that holds the configuration information
- *
- * Return 0 on success, negative on failure.
- *
- * Receives configuration information from MOST core and initialize the
- * corresponding channel.
- */
-static int configure_channel(struct most_interface *most_iface,
-			     int ch_idx,
-			     struct most_channel_config *channel_config)
-{
-	struct hdm_i2c *dev = to_hdm(most_iface);
-
-	BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
-	BUG_ON(dev->is_open[ch_idx]);
-
-	if (channel_config->data_type != MOST_CH_CONTROL) {
-		pr_err("bad data type for channel %d\n", ch_idx);
-		return -EPERM;
-	}
-
-	if (channel_config->direction != dev->capabilities[ch_idx].direction) {
-		pr_err("bad direction for channel %d\n", ch_idx);
-		return -EPERM;
-	}
-
-	if ((channel_config->direction == MOST_CH_RX) && (dev->polling_mode)) {
-		schedule_delayed_work(&dev->rx.dwork,
-				      msecs_to_jiffies(MSEC_PER_SEC / 4));
-	}
-	dev->is_open[ch_idx] = true;
-
-	return 0;
-}
-
-/**
- * enqueue - called from MOST core to enqueue a buffer for data transfer
- * @iface: intended interface
- * @channel: ID of the channel the buffer is intended for
- * @mbo: pointer to the buffer object
- *
- * Return 0 on success, negative on failure.
- *
- * Transmit the data over I2C if it is a "write" request or push the buffer into
- * list if it is an "read" request
- */
-static int enqueue(struct most_interface *most_iface,
-		   int ch_idx, struct mbo *mbo)
-{
-	struct hdm_i2c *dev = to_hdm(most_iface);
-	int ret;
-
-	BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
-	BUG_ON(!dev->is_open[ch_idx]);
-
-	if (ch_idx == CH_RX) {
-		/* RX */
-		mutex_lock(&dev->rx.list_mutex);
-		list_add_tail(&mbo->list, &dev->rx.list);
-		mutex_unlock(&dev->rx.list_mutex);
-		wake_up_interruptible(&dev->rx.waitq);
-	} else {
-		/* TX */
-		ret = i2c_master_send(dev->client, mbo->virt_address,
-				      mbo->buffer_length);
-		if (ret <= 0) {
-			mbo->processed_length = 0;
-			mbo->status = MBO_E_INVAL;
-		} else {
-			mbo->processed_length = mbo->buffer_length;
-			mbo->status = MBO_SUCCESS;
-		}
-		mbo->complete(mbo);
-	}
-
-	return 0;
-}
-
-/**
- * poison_channel - called from MOST core to poison buffers of a channel
- * @iface: pointer to the interface the channel to be poisoned belongs to
- * @channel_id: corresponding channel ID
- *
- * Return 0 on success, negative on failure.
- *
- * If channel direction is RX, complete the buffers in list with
- * status MBO_E_CLOSE
- */
-static int poison_channel(struct most_interface *most_iface,
-			  int ch_idx)
-{
-	struct hdm_i2c *dev = to_hdm(most_iface);
-	struct mbo *mbo;
-
-	BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
-	BUG_ON(!dev->is_open[ch_idx]);
-
-	dev->is_open[ch_idx] = false;
-
-	if (ch_idx == CH_RX) {
-		mutex_lock(&dev->rx.list_mutex);
-		while (!list_empty(&dev->rx.list)) {
-			mbo = list_first_mbo(&dev->rx.list);
-			list_del(&mbo->list);
-			mutex_unlock(&dev->rx.list_mutex);
-
-			mbo->processed_length = 0;
-			mbo->status = MBO_E_CLOSE;
-			mbo->complete(mbo);
-
-			mutex_lock(&dev->rx.list_mutex);
-		}
-		mutex_unlock(&dev->rx.list_mutex);
-		wake_up_interruptible(&dev->rx.waitq);
-	}
-
-	return 0;
-}
-
-static void do_rx_work(struct hdm_i2c *dev)
-{
-	struct mbo *mbo;
-	unsigned char msg[MAX_BUF_SIZE_CONTROL];
-	int ret, ch_idx = CH_RX;
-	u16 pml, data_size;
-
-	/* Read PML (2 bytes) */
-	ret = i2c_master_recv(dev->client, msg, 2);
-	if (ret <= 0) {
-		pr_err("Failed to receive PML\n");
-		return;
-	}
-
-	pml = (msg[0] << 8) | msg[1];
-	if (!pml)
-		return;
-
-	data_size = pml + 2;
-
-	/* Read the whole message, including PML */
-	ret = i2c_master_recv(dev->client, msg, data_size);
-	if (ret <= 0) {
-		pr_err("Failed to receive a Port Message\n");
-		return;
-	}
-
-	for (;;) {
-		/* Conditions to wait for: poisoned channel or free buffer
-		 * available for reading
-		 */
-		if (wait_event_interruptible(dev->rx.waitq,
-					     !dev->is_open[ch_idx] ||
-					     !list_empty(&dev->rx.list))) {
-			pr_err("wait_event_interruptible() failed\n");
-			return;
-		}
-
-		if (!dev->is_open[ch_idx])
-			return;
-
-		mutex_lock(&dev->rx.list_mutex);
-
-		/* list may be empty if poison or remove is called */
-		if (!list_empty(&dev->rx.list))
-			break;
-
-		mutex_unlock(&dev->rx.list_mutex);
-	}
-
-	mbo = list_first_mbo(&dev->rx.list);
-	list_del(&mbo->list);
-	mutex_unlock(&dev->rx.list_mutex);
-
-	mbo->processed_length = min(data_size, mbo->buffer_length);
-	memcpy(mbo->virt_address, msg, mbo->processed_length);
-	mbo->status = MBO_SUCCESS;
-	mbo->complete(mbo);
-}
-
-/**
- * pending_rx_work - Read pending messages through I2C
- * @work: definition of this work item
- *
- * Invoked by the Interrupt Service Routine, most_irq_handler()
- */
-static void pending_rx_work(struct work_struct *work)
-{
-	struct hdm_i2c *dev = container_of(work, struct hdm_i2c, rx.dwork.work);
-
-	do_rx_work(dev);
-
-	if (dev->polling_mode) {
-		if (dev->is_open[CH_RX])
-			schedule_delayed_work(&dev->rx.dwork,
-					      msecs_to_jiffies(MSEC_PER_SEC
-							       / scan_rate));
-	} else {
-		enable_irq(dev->client->irq);
-	}
-}
-
-/*
- * most_irq_handler - Interrupt Service Routine
- * @irq: irq number
- * @_dev: private data
- *
- * Schedules a delayed work
- *
- * By default the interrupt line behavior is Active Low. Once an interrupt is
- * generated by the device, until driver clears the interrupt (by reading
- * the PMP message), device keeps the interrupt line in low state. Since i2c
- * read is done in work queue, the interrupt line must be disabled temporarily
- * to avoid ISR being called repeatedly. Re-enable the interrupt in workqueue,
- * after reading the message.
- *
- * Note: If we use the interrupt line in Falling edge mode, there is a
- * possibility to miss interrupts when ISR is getting executed.
- *
- */
-static irqreturn_t most_irq_handler(int irq, void *_dev)
-{
-	struct hdm_i2c *dev = _dev;
-
-	disable_irq_nosync(irq);
-
-	schedule_delayed_work(&dev->rx.dwork, 0);
-
-	return IRQ_HANDLED;
-}
-
-/*
- * i2c_probe - i2c probe handler
- * @client: i2c client device structure
- * @id: i2c client device id
- *
- * Return 0 on success, negative on failure.
- *
- * Register the i2c client device as a MOST interface
- */
-static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
-	struct hdm_i2c *dev;
-	int ret, i;
-	struct kobject *kobj;
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return -ENOMEM;
-
-	/* ID format: i2c-<bus>-<address> */
-	snprintf(dev->name, sizeof(dev->name), "i2c-%d-%04x",
-		 client->adapter->nr, client->addr);
-
-	for (i = 0; i < NUM_CHANNELS; i++) {
-		dev->is_open[i] = false;
-		dev->capabilities[i].data_type = MOST_CH_CONTROL;
-		dev->capabilities[i].num_buffers_packet = MAX_BUFFERS_CONTROL;
-		dev->capabilities[i].buffer_size_packet = MAX_BUF_SIZE_CONTROL;
-	}
-	dev->capabilities[CH_RX].direction = MOST_CH_RX;
-	dev->capabilities[CH_RX].name_suffix = "rx";
-	dev->capabilities[CH_TX].direction = MOST_CH_TX;
-	dev->capabilities[CH_TX].name_suffix = "tx";
-
-	dev->most_iface.interface = ITYPE_I2C;
-	dev->most_iface.description = dev->name;
-	dev->most_iface.num_channels = NUM_CHANNELS;
-	dev->most_iface.channel_vector = dev->capabilities;
-	dev->most_iface.configure = configure_channel;
-	dev->most_iface.enqueue = enqueue;
-	dev->most_iface.poison_channel = poison_channel;
-
-	INIT_LIST_HEAD(&dev->rx.list);
-	mutex_init(&dev->rx.list_mutex);
-	init_waitqueue_head(&dev->rx.waitq);
-
-	INIT_DELAYED_WORK(&dev->rx.dwork, pending_rx_work);
-
-	dev->client = client;
-	i2c_set_clientdata(client, dev);
-
-	kobj = most_register_interface(&dev->most_iface);
-	if (IS_ERR(kobj)) {
-		pr_err("Failed to register i2c as a MOST interface\n");
-		kfree(dev);
-		return PTR_ERR(kobj);
-	}
-
-	dev->polling_mode = polling_req || client->irq <= 0;
-	if (!dev->polling_mode) {
-		pr_info("Requesting IRQ: %d\n", client->irq);
-		ret = request_irq(client->irq, most_irq_handler, 0,
-				  client->name, dev);
-		if (ret) {
-			pr_info("IRQ request failed: %d, falling back to polling\n",
-				ret);
-			dev->polling_mode = true;
-		}
-	}
-
-	if (dev->polling_mode)
-		pr_info("Using polling at rate: %d times/sec\n", scan_rate);
-
-	return 0;
-}
-
-/*
- * i2c_remove - i2c remove handler
- * @client: i2c client device structure
- *
- * Return 0 on success.
- *
- * Unregister the i2c client device as a MOST interface
- */
-static int i2c_remove(struct i2c_client *client)
-{
-	struct hdm_i2c *dev = i2c_get_clientdata(client);
-	int i;
-
-	if (!dev->polling_mode)
-		free_irq(client->irq, dev);
-
-	most_deregister_interface(&dev->most_iface);
-
-	for (i = 0 ; i < NUM_CHANNELS; i++)
-		if (dev->is_open[i])
-			poison_channel(&dev->most_iface, i);
-	cancel_delayed_work_sync(&dev->rx.dwork);
-	kfree(dev);
-
-	return 0;
-}
-
-static const struct i2c_device_id i2c_id[] = {
-	{ "most_i2c", 0 },
-	{ }, /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(i2c, i2c_id);
-
-static struct i2c_driver i2c_driver = {
-	.driver = {
-		.name = "hdm_i2c",
-	},
-	.probe = i2c_probe,
-	.remove = i2c_remove,
-	.id_table = i2c_id,
-};
-
-module_i2c_driver(i2c_driver);
-
-MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
-MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
-MODULE_DESCRIPTION("I2C Hardware Dependent Module");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/hdm-usb/Kconfig b/drivers/staging/most/hdm-usb/Kconfig
deleted file mode 100644
index 487f1f3..0000000
--- a/drivers/staging/most/hdm-usb/Kconfig
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# MOST USB configuration
-#
-
-config HDM_USB
-	tristate "USB HDM"
-	depends on USB && NET
-
-	---help---
-	  Say Y here if you want to connect via USB to network tranceiver.
-	  This device driver depends on the networking AIM.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called hdm_usb.
diff --git a/drivers/staging/most/hdm-usb/Makefile b/drivers/staging/most/hdm-usb/Makefile
deleted file mode 100644
index 6bbacb4..0000000
--- a/drivers/staging/most/hdm-usb/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-obj-$(CONFIG_HDM_USB) += hdm_usb.o
-
-ccflags-y += -Idrivers/staging/most/mostcore/
-ccflags-y += -Idrivers/staging/most/aim-network/
diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c
deleted file mode 100644
index 85775da..0000000
--- a/drivers/staging/most/hdm-usb/hdm_usb.c
+++ /dev/null
@@ -1,1307 +0,0 @@
-/*
- * hdm_usb.c - Hardware dependent module for USB
- *
- * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/usb.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/cdev.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/completion.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-#include <linux/sysfs.h>
-#include <linux/dma-mapping.h>
-#include <linux/etherdevice.h>
-#include <linux/uaccess.h>
-#include "mostcore.h"
-
-#define USB_MTU			512
-#define NO_ISOCHRONOUS_URB	0
-#define AV_PACKETS_PER_XACT	2
-#define BUF_CHAIN_SIZE		0xFFFF
-#define MAX_NUM_ENDPOINTS	30
-#define MAX_SUFFIX_LEN		10
-#define MAX_STRING_LEN		80
-#define MAX_BUF_SIZE		0xFFFF
-
-#define USB_VENDOR_ID_SMSC	0x0424  /* VID: SMSC */
-#define USB_DEV_ID_BRDG		0xC001  /* PID: USB Bridge */
-#define USB_DEV_ID_OS81118	0xCF18  /* PID: USB OS81118 */
-#define USB_DEV_ID_OS81119	0xCF19  /* PID: USB OS81119 */
-#define USB_DEV_ID_OS81210	0xCF30  /* PID: USB OS81210 */
-/* DRCI Addresses */
-#define DRCI_REG_NI_STATE	0x0100
-#define DRCI_REG_PACKET_BW	0x0101
-#define DRCI_REG_NODE_ADDR	0x0102
-#define DRCI_REG_NODE_POS	0x0103
-#define DRCI_REG_MEP_FILTER	0x0140
-#define DRCI_REG_HASH_TBL0	0x0141
-#define DRCI_REG_HASH_TBL1	0x0142
-#define DRCI_REG_HASH_TBL2	0x0143
-#define DRCI_REG_HASH_TBL3	0x0144
-#define DRCI_REG_HW_ADDR_HI	0x0145
-#define DRCI_REG_HW_ADDR_MI	0x0146
-#define DRCI_REG_HW_ADDR_LO	0x0147
-#define DRCI_REG_BASE		0x1100
-#define DRCI_COMMAND		0x02
-#define DRCI_READ_REQ		0xA0
-#define DRCI_WRITE_REQ		0xA1
-
-/**
- * struct most_dci_obj - Direct Communication Interface
- * @kobj:position in sysfs
- * @usb_device: pointer to the usb device
- * @reg_addr: register address for arbitrary DCI access
- */
-struct most_dci_obj {
-	struct kobject kobj;
-	struct usb_device *usb_device;
-	u16 reg_addr;
-};
-
-#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj)
-
-struct most_dev;
-
-struct clear_hold_work {
-	struct work_struct ws;
-	struct most_dev *mdev;
-	unsigned int channel;
-	int pipe;
-};
-
-#define to_clear_hold_work(w) container_of(w, struct clear_hold_work, ws)
-
-/**
- * struct most_dev - holds all usb interface specific stuff
- * @parent: parent object in sysfs
- * @usb_device: pointer to usb device
- * @iface: hardware interface
- * @cap: channel capabilities
- * @conf: channel configuration
- * @dci: direct communication interface of hardware
- * @ep_address: endpoint address table
- * @description: device description
- * @suffix: suffix for channel name
- * @channel_lock: synchronize channel access
- * @padding_active: indicates channel uses padding
- * @is_channel_healthy: health status table of each channel
- * @busy_urbs: list of anchored items
- * @io_mutex: synchronize I/O with disconnect
- * @link_stat_timer: timer for link status reports
- * @poll_work_obj: work for polling link status
- */
-struct most_dev {
-	struct kobject *parent;
-	struct usb_device *usb_device;
-	struct most_interface iface;
-	struct most_channel_capability *cap;
-	struct most_channel_config *conf;
-	struct most_dci_obj *dci;
-	u8 *ep_address;
-	char description[MAX_STRING_LEN];
-	char suffix[MAX_NUM_ENDPOINTS][MAX_SUFFIX_LEN];
-	spinlock_t channel_lock[MAX_NUM_ENDPOINTS]; /* sync channel access */
-	bool padding_active[MAX_NUM_ENDPOINTS];
-	bool is_channel_healthy[MAX_NUM_ENDPOINTS];
-	struct clear_hold_work clear_work[MAX_NUM_ENDPOINTS];
-	struct usb_anchor *busy_urbs;
-	struct mutex io_mutex;
-	struct timer_list link_stat_timer;
-	struct work_struct poll_work_obj;
-	void (*on_netinfo)(struct most_interface *, unsigned char,
-			   unsigned char *);
-};
-
-#define to_mdev(d) container_of(d, struct most_dev, iface)
-#define to_mdev_from_work(w) container_of(w, struct most_dev, poll_work_obj)
-
-static void wq_clear_halt(struct work_struct *wq_obj);
-static void wq_netinfo(struct work_struct *wq_obj);
-
-/**
- * drci_rd_reg - read a DCI register
- * @dev: usb device
- * @reg: register address
- * @buf: buffer to store data
- *
- * This is reads data from INIC's direct register communication interface
- */
-static inline int drci_rd_reg(struct usb_device *dev, u16 reg, u16 *buf)
-{
-	int retval;
-	__le16 *dma_buf = kzalloc(sizeof(*dma_buf), GFP_KERNEL);
-	u8 req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-
-	if (!dma_buf)
-		return -ENOMEM;
-
-	retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-				 DRCI_READ_REQ, req_type,
-				 0x0000,
-				 reg, dma_buf, sizeof(*dma_buf), 5 * HZ);
-	*buf = le16_to_cpu(*dma_buf);
-	kfree(dma_buf);
-
-	return retval;
-}
-
-/**
- * drci_wr_reg - write a DCI register
- * @dev: usb device
- * @reg: register address
- * @data: data to write
- *
- * This is writes data to INIC's direct register communication interface
- */
-static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data)
-{
-	return usb_control_msg(dev,
-			       usb_sndctrlpipe(dev, 0),
-			       DRCI_WRITE_REQ,
-			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			       data,
-			       reg,
-			       NULL,
-			       0,
-			       5 * HZ);
-}
-
-static inline int start_sync_ep(struct usb_device *usb_dev, u16 ep)
-{
-	return drci_wr_reg(usb_dev, DRCI_REG_BASE + DRCI_COMMAND + ep * 16, 1);
-}
-
-/**
- * get_stream_frame_size - calculate frame size of current configuration
- * @cfg: channel configuration
- */
-static unsigned int get_stream_frame_size(struct most_channel_config *cfg)
-{
-	unsigned int frame_size = 0;
-	unsigned int sub_size = cfg->subbuffer_size;
-
-	if (!sub_size) {
-		pr_warn("Misconfig: Subbuffer size zero.\n");
-		return frame_size;
-	}
-	switch (cfg->data_type) {
-	case MOST_CH_ISOC:
-		frame_size = AV_PACKETS_PER_XACT * sub_size;
-		break;
-	case MOST_CH_SYNC:
-		if (cfg->packets_per_xact == 0) {
-			pr_warn("Misconfig: Packets per XACT zero\n");
-			frame_size = 0;
-		} else if (cfg->packets_per_xact == 0xFF) {
-			frame_size = (USB_MTU / sub_size) * sub_size;
-		} else {
-			frame_size = cfg->packets_per_xact * sub_size;
-		}
-		break;
-	default:
-		pr_warn("Query frame size of non-streaming channel\n");
-		break;
-	}
-	return frame_size;
-}
-
-/**
- * hdm_poison_channel - mark buffers of this channel as invalid
- * @iface: pointer to the interface
- * @channel: channel ID
- *
- * This unlinks all URBs submitted to the HCD,
- * calls the associated completion function of the core and removes
- * them from the list.
- *
- * Returns 0 on success or error code otherwise.
- */
-static int hdm_poison_channel(struct most_interface *iface, int channel)
-{
-	struct most_dev *mdev = to_mdev(iface);
-	unsigned long flags;
-	spinlock_t *lock; /* temp. lock */
-
-	if (unlikely(!iface)) {
-		dev_warn(&mdev->usb_device->dev, "Poison: Bad interface.\n");
-		return -EIO;
-	}
-	if (unlikely(channel < 0 || channel >= iface->num_channels)) {
-		dev_warn(&mdev->usb_device->dev, "Channel ID out of range.\n");
-		return -ECHRNG;
-	}
-
-	lock = mdev->channel_lock + channel;
-	spin_lock_irqsave(lock, flags);
-	mdev->is_channel_healthy[channel] = false;
-	spin_unlock_irqrestore(lock, flags);
-
-	cancel_work_sync(&mdev->clear_work[channel].ws);
-
-	mutex_lock(&mdev->io_mutex);
-	usb_kill_anchored_urbs(&mdev->busy_urbs[channel]);
-	if (mdev->padding_active[channel])
-		mdev->padding_active[channel] = false;
-
-	if (mdev->conf[channel].data_type == MOST_CH_ASYNC) {
-		del_timer_sync(&mdev->link_stat_timer);
-		cancel_work_sync(&mdev->poll_work_obj);
-	}
-	mutex_unlock(&mdev->io_mutex);
-	return 0;
-}
-
-/**
- * hdm_add_padding - add padding bytes
- * @mdev: most device
- * @channel: channel ID
- * @mbo: buffer object
- *
- * This inserts the INIC hardware specific padding bytes into a streaming
- * channel's buffer
- */
-static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo)
-{
-	struct most_channel_config *conf = &mdev->conf[channel];
-	unsigned int frame_size = get_stream_frame_size(conf);
-	unsigned int j, num_frames;
-
-	if (!frame_size)
-		return -EIO;
-	num_frames = mbo->buffer_length / frame_size;
-
-	if (num_frames < 1) {
-		dev_err(&mdev->usb_device->dev,
-			"Missed minimal transfer unit.\n");
-		return -EIO;
-	}
-
-	for (j = num_frames - 1; j > 0; j--)
-		memmove(mbo->virt_address + j * USB_MTU,
-			mbo->virt_address + j * frame_size,
-			frame_size);
-	mbo->buffer_length = num_frames * USB_MTU;
-	return 0;
-}
-
-/**
- * hdm_remove_padding - remove padding bytes
- * @mdev: most device
- * @channel: channel ID
- * @mbo: buffer object
- *
- * This takes the INIC hardware specific padding bytes off a streaming
- * channel's buffer.
- */
-static int hdm_remove_padding(struct most_dev *mdev, int channel,
-			      struct mbo *mbo)
-{
-	struct most_channel_config *const conf = &mdev->conf[channel];
-	unsigned int frame_size = get_stream_frame_size(conf);
-	unsigned int j, num_frames;
-
-	if (!frame_size)
-		return -EIO;
-	num_frames = mbo->processed_length / USB_MTU;
-
-	for (j = 1; j < num_frames; j++)
-		memmove(mbo->virt_address + frame_size * j,
-			mbo->virt_address + USB_MTU * j,
-			frame_size);
-
-	mbo->processed_length = frame_size * num_frames;
-	return 0;
-}
-
-/**
- * hdm_write_completion - completion function for submitted Tx URBs
- * @urb: the URB that has been completed
- *
- * This checks the status of the completed URB. In case the URB has been
- * unlinked before, it is immediately freed. On any other error the MBO
- * transfer flag is set. On success it frees allocated resources and calls
- * the completion function.
- *
- * Context: interrupt!
- */
-static void hdm_write_completion(struct urb *urb)
-{
-	struct mbo *mbo = urb->context;
-	struct most_dev *mdev = to_mdev(mbo->ifp);
-	unsigned int channel = mbo->hdm_channel_id;
-	struct device *dev = &mdev->usb_device->dev;
-	spinlock_t *lock = mdev->channel_lock + channel;
-	unsigned long flags;
-
-	spin_lock_irqsave(lock, flags);
-
-	mbo->processed_length = 0;
-	mbo->status = MBO_E_INVAL;
-	if (likely(mdev->is_channel_healthy[channel])) {
-		switch (urb->status) {
-		case 0:
-		case -ESHUTDOWN:
-			mbo->processed_length = urb->actual_length;
-			mbo->status = MBO_SUCCESS;
-			break;
-		case -EPIPE:
-			dev_warn(dev, "Broken OUT pipe detected\n");
-			mdev->is_channel_healthy[channel] = false;
-			mdev->clear_work[channel].pipe = urb->pipe;
-			schedule_work(&mdev->clear_work[channel].ws);
-			break;
-		case -ENODEV:
-		case -EPROTO:
-			mbo->status = MBO_E_CLOSE;
-			break;
-		}
-	}
-
-	spin_unlock_irqrestore(lock, flags);
-
-	if (likely(mbo->complete))
-		mbo->complete(mbo);
-	usb_free_urb(urb);
-}
-
-/**
- * hdm_read_completion - completion function for submitted Rx URBs
- * @urb: the URB that has been completed
- *
- * This checks the status of the completed URB. In case the URB has been
- * unlinked before it is immediately freed. On any other error the MBO transfer
- * flag is set. On success it frees allocated resources, removes
- * padding bytes -if necessary- and calls the completion function.
- *
- * Context: interrupt!
- *
- * **************************************************************************
- *                   Error codes returned by in urb->status
- *                   or in iso_frame_desc[n].status (for ISO)
- * *************************************************************************
- *
- * USB device drivers may only test urb status values in completion handlers.
- * This is because otherwise there would be a race between HCDs updating
- * these values on one CPU, and device drivers testing them on another CPU.
- *
- * A transfer's actual_length may be positive even when an error has been
- * reported.  That's because transfers often involve several packets, so that
- * one or more packets could finish before an error stops further endpoint I/O.
- *
- * For isochronous URBs, the urb status value is non-zero only if the URB is
- * unlinked, the device is removed, the host controller is disabled or the total
- * transferred length is less than the requested length and the URB_SHORT_NOT_OK
- * flag is set.  Completion handlers for isochronous URBs should only see
- * urb->status set to zero, -ENOENT, -ECONNRESET, -ESHUTDOWN, or -EREMOTEIO.
- * Individual frame descriptor status fields may report more status codes.
- *
- *
- * 0			Transfer completed successfully
- *
- * -ENOENT		URB was synchronously unlinked by usb_unlink_urb
- *
- * -EINPROGRESS		URB still pending, no results yet
- *			(That is, if drivers see this it's a bug.)
- *
- * -EPROTO (*, **)	a) bitstuff error
- *			b) no response packet received within the
- *			   prescribed bus turn-around time
- *			c) unknown USB error
- *
- * -EILSEQ (*, **)	a) CRC mismatch
- *			b) no response packet received within the
- *			   prescribed bus turn-around time
- *			c) unknown USB error
- *
- *			Note that often the controller hardware does not
- *			distinguish among cases a), b), and c), so a
- *			driver cannot tell whether there was a protocol
- *			error, a failure to respond (often caused by
- *			device disconnect), or some other fault.
- *
- * -ETIME (**)		No response packet received within the prescribed
- *			bus turn-around time.  This error may instead be
- *			reported as -EPROTO or -EILSEQ.
- *
- * -ETIMEDOUT		Synchronous USB message functions use this code
- *			to indicate timeout expired before the transfer
- *			completed, and no other error was reported by HC.
- *
- * -EPIPE (**)		Endpoint stalled.  For non-control endpoints,
- *			reset this status with usb_clear_halt().
- *
- * -ECOMM		During an IN transfer, the host controller
- *			received data from an endpoint faster than it
- *			could be written to system memory
- *
- * -ENOSR		During an OUT transfer, the host controller
- *			could not retrieve data from system memory fast
- *			enough to keep up with the USB data rate
- *
- * -EOVERFLOW (*)	The amount of data returned by the endpoint was
- *			greater than either the max packet size of the
- *			endpoint or the remaining buffer size.  "Babble".
- *
- * -EREMOTEIO		The data read from the endpoint did not fill the
- *			specified buffer, and URB_SHORT_NOT_OK was set in
- *			urb->transfer_flags.
- *
- * -ENODEV		Device was removed.  Often preceded by a burst of
- *			other errors, since the hub driver doesn't detect
- *			device removal events immediately.
- *
- * -EXDEV		ISO transfer only partially completed
- *			(only set in iso_frame_desc[n].status, not urb->status)
- *
- * -EINVAL		ISO madness, if this happens: Log off and go home
- *
- * -ECONNRESET		URB was asynchronously unlinked by usb_unlink_urb
- *
- * -ESHUTDOWN		The device or host controller has been disabled due
- *			to some problem that could not be worked around,
- *			such as a physical disconnect.
- *
- *
- * (*) Error codes like -EPROTO, -EILSEQ and -EOVERFLOW normally indicate
- * hardware problems such as bad devices (including firmware) or cables.
- *
- * (**) This is also one of several codes that different kinds of host
- * controller use to indicate a transfer has failed because of device
- * disconnect.  In the interval before the hub driver starts disconnect
- * processing, devices may receive such fault reports for every request.
- *
- * See <https://www.kernel.org/doc/Documentation/driver-api/usb/error-codes.rst>
- */
-static void hdm_read_completion(struct urb *urb)
-{
-	struct mbo *mbo = urb->context;
-	struct most_dev *mdev = to_mdev(mbo->ifp);
-	unsigned int channel = mbo->hdm_channel_id;
-	struct device *dev = &mdev->usb_device->dev;
-	spinlock_t *lock = mdev->channel_lock + channel;
-	unsigned long flags;
-
-	spin_lock_irqsave(lock, flags);
-
-	mbo->processed_length = 0;
-	mbo->status = MBO_E_INVAL;
-	if (likely(mdev->is_channel_healthy[channel])) {
-		switch (urb->status) {
-		case 0:
-		case -ESHUTDOWN:
-			mbo->processed_length = urb->actual_length;
-			mbo->status = MBO_SUCCESS;
-			if (mdev->padding_active[channel] &&
-			    hdm_remove_padding(mdev, channel, mbo)) {
-				mbo->processed_length = 0;
-				mbo->status = MBO_E_INVAL;
-			}
-			break;
-		case -EPIPE:
-			dev_warn(dev, "Broken IN pipe detected\n");
-			mdev->is_channel_healthy[channel] = false;
-			mdev->clear_work[channel].pipe = urb->pipe;
-			schedule_work(&mdev->clear_work[channel].ws);
-			break;
-		case -ENODEV:
-		case -EPROTO:
-			mbo->status = MBO_E_CLOSE;
-			break;
-		case -EOVERFLOW:
-			dev_warn(dev, "Babble on IN pipe detected\n");
-			break;
-		}
-	}
-
-	spin_unlock_irqrestore(lock, flags);
-
-	if (likely(mbo->complete))
-		mbo->complete(mbo);
-	usb_free_urb(urb);
-}
-
-/**
- * hdm_enqueue - receive a buffer to be used for data transfer
- * @iface: interface to enqueue to
- * @channel: ID of the channel
- * @mbo: pointer to the buffer object
- *
- * This allocates a new URB and fills it according to the channel
- * that is being used for transmission of data. Before the URB is
- * submitted it is stored in the private anchor list.
- *
- * Returns 0 on success. On any error the URB is freed and a error code
- * is returned.
- *
- * Context: Could in _some_ cases be interrupt!
- */
-static int hdm_enqueue(struct most_interface *iface, int channel,
-		       struct mbo *mbo)
-{
-	struct most_dev *mdev;
-	struct most_channel_config *conf;
-	struct device *dev;
-	int retval = 0;
-	struct urb *urb;
-	unsigned long length;
-	void *virt_address;
-
-	if (unlikely(!iface || !mbo))
-		return -EIO;
-	if (unlikely(iface->num_channels <= channel || channel < 0))
-		return -ECHRNG;
-
-	mdev = to_mdev(iface);
-	conf = &mdev->conf[channel];
-	dev = &mdev->usb_device->dev;
-
-	if (!mdev->usb_device)
-		return -ENODEV;
-
-	urb = usb_alloc_urb(NO_ISOCHRONOUS_URB, GFP_ATOMIC);
-	if (!urb)
-		return -ENOMEM;
-
-	if ((conf->direction & MOST_CH_TX) && mdev->padding_active[channel] &&
-	    hdm_add_padding(mdev, channel, mbo)) {
-		retval = -EIO;
-		goto _error;
-	}
-
-	urb->transfer_dma = mbo->bus_address;
-	virt_address = mbo->virt_address;
-	length = mbo->buffer_length;
-
-	if (conf->direction & MOST_CH_TX) {
-		usb_fill_bulk_urb(urb, mdev->usb_device,
-				  usb_sndbulkpipe(mdev->usb_device,
-						  mdev->ep_address[channel]),
-				  virt_address,
-				  length,
-				  hdm_write_completion,
-				  mbo);
-		if (conf->data_type != MOST_CH_ISOC)
-			urb->transfer_flags |= URB_ZERO_PACKET;
-	} else {
-		usb_fill_bulk_urb(urb, mdev->usb_device,
-				  usb_rcvbulkpipe(mdev->usb_device,
-						  mdev->ep_address[channel]),
-				  virt_address,
-				  length + conf->extra_len,
-				  hdm_read_completion,
-				  mbo);
-	}
-	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	usb_anchor_urb(urb, &mdev->busy_urbs[channel]);
-
-	retval = usb_submit_urb(urb, GFP_KERNEL);
-	if (retval) {
-		dev_err(dev, "URB submit failed with error %d.\n", retval);
-		goto _error_1;
-	}
-	return 0;
-
-_error_1:
-	usb_unanchor_urb(urb);
-_error:
-	usb_free_urb(urb);
-	return retval;
-}
-
-/**
- * hdm_configure_channel - receive channel configuration from core
- * @iface: interface
- * @channel: channel ID
- * @conf: structure that holds the configuration information
- *
- * The attached network interface controller (NIC) supports a padding mode
- * to avoid short packets on USB, hence increasing the performance due to a
- * lower interrupt load. This mode is default for synchronous data and can
- * be switched on for isochronous data. In case padding is active the
- * driver needs to know the frame size of the payload in order to calculate
- * the number of bytes it needs to pad when transmitting or to cut off when
- * receiving data.
- *
- */
-static int hdm_configure_channel(struct most_interface *iface, int channel,
-				 struct most_channel_config *conf)
-{
-	unsigned int num_frames;
-	unsigned int frame_size;
-	struct most_dev *mdev = to_mdev(iface);
-	struct device *dev = &mdev->usb_device->dev;
-
-	mdev->is_channel_healthy[channel] = true;
-	mdev->clear_work[channel].channel = channel;
-	mdev->clear_work[channel].mdev = mdev;
-	INIT_WORK(&mdev->clear_work[channel].ws, wq_clear_halt);
-
-	if (unlikely(!iface || !conf)) {
-		dev_err(dev, "Bad interface or config pointer.\n");
-		return -EINVAL;
-	}
-	if (unlikely(channel < 0 || channel >= iface->num_channels)) {
-		dev_err(dev, "Channel ID out of range.\n");
-		return -EINVAL;
-	}
-	if (!conf->num_buffers || !conf->buffer_size) {
-		dev_err(dev, "Misconfig: buffer size or #buffers zero.\n");
-		return -EINVAL;
-	}
-
-	if (conf->data_type != MOST_CH_SYNC &&
-	    !(conf->data_type == MOST_CH_ISOC &&
-	      conf->packets_per_xact != 0xFF)) {
-		mdev->padding_active[channel] = false;
-		/*
-		 * Since the NIC's padding mode is not going to be
-		 * used, we can skip the frame size calculations and
-		 * move directly on to exit.
-		 */
-		goto exit;
-	}
-
-	mdev->padding_active[channel] = true;
-
-	frame_size = get_stream_frame_size(conf);
-	if (frame_size == 0 || frame_size > USB_MTU) {
-		dev_warn(dev, "Misconfig: frame size wrong\n");
-		return -EINVAL;
-	}
-
-	num_frames = conf->buffer_size / frame_size;
-
-	if (conf->buffer_size % frame_size) {
-		u16 old_size = conf->buffer_size;
-
-		conf->buffer_size = num_frames * frame_size;
-		dev_warn(dev, "%s: fixed buffer size (%d -> %d)\n",
-			 mdev->suffix[channel], old_size, conf->buffer_size);
-	}
-
-	/* calculate extra length to comply w/ HW padding */
-	conf->extra_len = num_frames * (USB_MTU - frame_size);
-
-exit:
-	mdev->conf[channel] = *conf;
-	if (conf->data_type == MOST_CH_ASYNC) {
-		u16 ep = mdev->ep_address[channel];
-
-		if (start_sync_ep(mdev->usb_device, ep) < 0)
-			dev_warn(dev, "sync for ep%02x failed", ep);
-	}
-	return 0;
-}
-
-/**
- * hdm_request_netinfo - request network information
- * @iface: pointer to interface
- * @channel: channel ID
- *
- * This is used as trigger to set up the link status timer that
- * polls for the NI state of the INIC every 2 seconds.
- *
- */
-static void hdm_request_netinfo(struct most_interface *iface, int channel,
-				void (*on_netinfo)(struct most_interface *,
-						   unsigned char,
-						   unsigned char *))
-{
-	struct most_dev *mdev;
-
-	BUG_ON(!iface);
-	mdev = to_mdev(iface);
-	mdev->on_netinfo = on_netinfo;
-	if (!on_netinfo)
-		return;
-
-	mdev->link_stat_timer.expires = jiffies + HZ;
-	mod_timer(&mdev->link_stat_timer, mdev->link_stat_timer.expires);
-}
-
-/**
- * link_stat_timer_handler - schedule work obtaining mac address and link status
- * @data: pointer to USB device instance
- *
- * The handler runs in interrupt context. That's why we need to defer the
- * tasks to a work queue.
- */
-static void link_stat_timer_handler(unsigned long data)
-{
-	struct most_dev *mdev = (struct most_dev *)data;
-
-	schedule_work(&mdev->poll_work_obj);
-	mdev->link_stat_timer.expires = jiffies + (2 * HZ);
-	add_timer(&mdev->link_stat_timer);
-}
-
-/**
- * wq_netinfo - work queue function to deliver latest networking information
- * @wq_obj: object that holds data for our deferred work to do
- *
- * This retrieves the network interface status of the USB INIC
- */
-static void wq_netinfo(struct work_struct *wq_obj)
-{
-	struct most_dev *mdev = to_mdev_from_work(wq_obj);
-	struct usb_device *usb_device = mdev->usb_device;
-	struct device *dev = &usb_device->dev;
-	u16 hi, mi, lo, link;
-	u8 hw_addr[6];
-
-	if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_HI, &hi) < 0) {
-		dev_err(dev, "Vendor request 'hw_addr_hi' failed\n");
-		return;
-	}
-
-	if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_MI, &mi) < 0) {
-		dev_err(dev, "Vendor request 'hw_addr_mid' failed\n");
-		return;
-	}
-
-	if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_LO, &lo) < 0) {
-		dev_err(dev, "Vendor request 'hw_addr_low' failed\n");
-		return;
-	}
-
-	if (drci_rd_reg(usb_device, DRCI_REG_NI_STATE, &link) < 0) {
-		dev_err(dev, "Vendor request 'link status' failed\n");
-		return;
-	}
-
-	hw_addr[0] = hi >> 8;
-	hw_addr[1] = hi;
-	hw_addr[2] = mi >> 8;
-	hw_addr[3] = mi;
-	hw_addr[4] = lo >> 8;
-	hw_addr[5] = lo;
-
-	if (mdev->on_netinfo)
-		mdev->on_netinfo(&mdev->iface, link, hw_addr);
-}
-
-/**
- * wq_clear_halt - work queue function
- * @wq_obj: work_struct object to execute
- *
- * This sends a clear_halt to the given USB pipe.
- */
-static void wq_clear_halt(struct work_struct *wq_obj)
-{
-	struct clear_hold_work *clear_work = to_clear_hold_work(wq_obj);
-	struct most_dev *mdev = clear_work->mdev;
-	unsigned int channel = clear_work->channel;
-	int pipe = clear_work->pipe;
-
-	mutex_lock(&mdev->io_mutex);
-	most_stop_enqueue(&mdev->iface, channel);
-	usb_kill_anchored_urbs(&mdev->busy_urbs[channel]);
-	if (usb_clear_halt(mdev->usb_device, pipe))
-		dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n");
-
-	mdev->is_channel_healthy[channel] = true;
-	most_resume_enqueue(&mdev->iface, channel);
-	mutex_unlock(&mdev->io_mutex);
-}
-
-/**
- * hdm_usb_fops - file operation table for USB driver
- */
-static const struct file_operations hdm_usb_fops = {
-	.owner = THIS_MODULE,
-};
-
-/**
- * usb_device_id - ID table for HCD device probing
- */
-static const struct usb_device_id usbid[] = {
-	{ USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), },
-	{ USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81118), },
-	{ USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81119), },
-	{ USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81210), },
-	{ } /* Terminating entry */
-};
-
-#define MOST_DCI_RO_ATTR(_name) \
-	struct most_dci_attribute most_dci_attr_##_name = \
-		__ATTR(_name, 0444, show_value, NULL)
-
-#define MOST_DCI_ATTR(_name) \
-	struct most_dci_attribute most_dci_attr_##_name = \
-		__ATTR(_name, 0644, show_value, store_value)
-
-#define MOST_DCI_WO_ATTR(_name) \
-	struct most_dci_attribute most_dci_attr_##_name = \
-		__ATTR(_name, 0200, NULL, store_value)
-
-/**
- * struct most_dci_attribute - to access the attributes of a dci object
- * @attr: attributes of a dci object
- * @show: pointer to the show function
- * @store: pointer to the store function
- */
-struct most_dci_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct most_dci_obj *d,
-			struct most_dci_attribute *attr,
-			char *buf);
-	ssize_t (*store)(struct most_dci_obj *d,
-			 struct most_dci_attribute *attr,
-			 const char *buf,
-			 size_t count);
-};
-
-#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr)
-
-/**
- * dci_attr_show - show function for dci object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- */
-static ssize_t dci_attr_show(struct kobject *kobj, struct attribute *attr,
-			     char *buf)
-{
-	struct most_dci_attribute *dci_attr = to_dci_attr(attr);
-	struct most_dci_obj *dci_obj = to_dci_obj(kobj);
-
-	if (!dci_attr->show)
-		return -EIO;
-
-	return dci_attr->show(dci_obj, dci_attr, buf);
-}
-
-/**
- * dci_attr_store - store function for dci object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- * @len: length of buffer
- */
-static ssize_t dci_attr_store(struct kobject *kobj,
-			      struct attribute *attr,
-			      const char *buf,
-			      size_t len)
-{
-	struct most_dci_attribute *dci_attr = to_dci_attr(attr);
-	struct most_dci_obj *dci_obj = to_dci_obj(kobj);
-
-	if (!dci_attr->store)
-		return -EIO;
-
-	return dci_attr->store(dci_obj, dci_attr, buf, len);
-}
-
-static const struct sysfs_ops most_dci_sysfs_ops = {
-	.show = dci_attr_show,
-	.store = dci_attr_store,
-};
-
-/**
- * most_dci_release - release function for dci object
- * @kobj: pointer to kobject
- *
- * This frees the memory allocated for the dci object
- */
-static void most_dci_release(struct kobject *kobj)
-{
-	struct most_dci_obj *dci_obj = to_dci_obj(kobj);
-
-	kfree(dci_obj);
-}
-
-struct regs {
-	const char *name;
-	u16 reg;
-};
-
-static const struct regs ro_regs[] = {
-	{ "ni_state", DRCI_REG_NI_STATE },
-	{ "packet_bandwidth", DRCI_REG_PACKET_BW },
-	{ "node_address", DRCI_REG_NODE_ADDR },
-	{ "node_position", DRCI_REG_NODE_POS },
-};
-
-static const struct regs rw_regs[] = {
-	{ "mep_filter", DRCI_REG_MEP_FILTER },
-	{ "mep_hash0", DRCI_REG_HASH_TBL0 },
-	{ "mep_hash1", DRCI_REG_HASH_TBL1 },
-	{ "mep_hash2", DRCI_REG_HASH_TBL2 },
-	{ "mep_hash3", DRCI_REG_HASH_TBL3 },
-	{ "mep_eui48_hi", DRCI_REG_HW_ADDR_HI },
-	{ "mep_eui48_mi", DRCI_REG_HW_ADDR_MI },
-	{ "mep_eui48_lo", DRCI_REG_HW_ADDR_LO },
-};
-
-static int get_stat_reg_addr(const struct regs *regs, int size,
-			     const char *name, u16 *reg_addr)
-{
-	int i;
-
-	for (i = 0; i < size; i++) {
-		if (!strcmp(name, regs[i].name)) {
-			*reg_addr = regs[i].reg;
-			return 0;
-		}
-	}
-	return -EFAULT;
-}
-
-#define get_static_reg_addr(regs, name, reg_addr) \
-	get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr)
-
-static ssize_t show_value(struct most_dci_obj *dci_obj,
-			  struct most_dci_attribute *attr, char *buf)
-{
-	const char *name = attr->attr.name;
-	u16 val;
-	u16 reg_addr;
-	int err;
-
-	if (!strcmp(name, "arb_address"))
-		return snprintf(buf, PAGE_SIZE, "%04x\n", dci_obj->reg_addr);
-
-	if (!strcmp(name, "arb_value"))
-		reg_addr = dci_obj->reg_addr;
-	else if (get_static_reg_addr(ro_regs, name, &reg_addr) &&
-		 get_static_reg_addr(rw_regs, name, &reg_addr))
-		return -EFAULT;
-
-	err = drci_rd_reg(dci_obj->usb_device, reg_addr, &val);
-	if (err < 0)
-		return err;
-
-	return snprintf(buf, PAGE_SIZE, "%04x\n", val);
-}
-
-static ssize_t store_value(struct most_dci_obj *dci_obj,
-			   struct most_dci_attribute *attr,
-			   const char *buf, size_t count)
-{
-	u16 val;
-	u16 reg_addr;
-	const char *name = attr->attr.name;
-	struct usb_device *usb_dev = dci_obj->usb_device;
-	int err = kstrtou16(buf, 16, &val);
-
-	if (err)
-		return err;
-
-	if (!strcmp(name, "arb_address")) {
-		dci_obj->reg_addr = val;
-		return count;
-	}
-
-	if (!strcmp(name, "arb_value"))
-		err = drci_wr_reg(usb_dev, dci_obj->reg_addr, val);
-	else if (!strcmp(name, "sync_ep"))
-		err = start_sync_ep(usb_dev, val);
-	else if (!get_static_reg_addr(rw_regs, name, &reg_addr))
-		err = drci_wr_reg(usb_dev, reg_addr, val);
-	else
-		return -EFAULT;
-
-	if (err < 0)
-		return err;
-
-	return count;
-}
-
-static MOST_DCI_RO_ATTR(ni_state);
-static MOST_DCI_RO_ATTR(packet_bandwidth);
-static MOST_DCI_RO_ATTR(node_address);
-static MOST_DCI_RO_ATTR(node_position);
-static MOST_DCI_WO_ATTR(sync_ep);
-static MOST_DCI_ATTR(mep_filter);
-static MOST_DCI_ATTR(mep_hash0);
-static MOST_DCI_ATTR(mep_hash1);
-static MOST_DCI_ATTR(mep_hash2);
-static MOST_DCI_ATTR(mep_hash3);
-static MOST_DCI_ATTR(mep_eui48_hi);
-static MOST_DCI_ATTR(mep_eui48_mi);
-static MOST_DCI_ATTR(mep_eui48_lo);
-static MOST_DCI_ATTR(arb_address);
-static MOST_DCI_ATTR(arb_value);
-
-/**
- * most_dci_def_attrs - array of default attribute files of the dci object
- */
-static struct attribute *most_dci_def_attrs[] = {
-	&most_dci_attr_ni_state.attr,
-	&most_dci_attr_packet_bandwidth.attr,
-	&most_dci_attr_node_address.attr,
-	&most_dci_attr_node_position.attr,
-	&most_dci_attr_sync_ep.attr,
-	&most_dci_attr_mep_filter.attr,
-	&most_dci_attr_mep_hash0.attr,
-	&most_dci_attr_mep_hash1.attr,
-	&most_dci_attr_mep_hash2.attr,
-	&most_dci_attr_mep_hash3.attr,
-	&most_dci_attr_mep_eui48_hi.attr,
-	&most_dci_attr_mep_eui48_mi.attr,
-	&most_dci_attr_mep_eui48_lo.attr,
-	&most_dci_attr_arb_address.attr,
-	&most_dci_attr_arb_value.attr,
-	NULL,
-};
-
-/**
- * DCI ktype
- */
-static struct kobj_type most_dci_ktype = {
-	.sysfs_ops = &most_dci_sysfs_ops,
-	.release = most_dci_release,
-	.default_attrs = most_dci_def_attrs,
-};
-
-/**
- * create_most_dci_obj - allocates a dci object
- * @parent: parent kobject
- *
- * This creates a dci object and registers it with sysfs.
- * Returns a pointer to the object or NULL when something went wrong.
- */
-static struct
-most_dci_obj *create_most_dci_obj(struct kobject *parent)
-{
-	struct most_dci_obj *most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL);
-	int retval;
-
-	if (!most_dci)
-		return NULL;
-
-	retval = kobject_init_and_add(&most_dci->kobj, &most_dci_ktype, parent,
-				      "dci");
-	if (retval) {
-		kobject_put(&most_dci->kobj);
-		return NULL;
-	}
-	return most_dci;
-}
-
-/**
- * destroy_most_dci_obj - DCI object release function
- * @p: pointer to dci object
- */
-static void destroy_most_dci_obj(struct most_dci_obj *p)
-{
-	kobject_put(&p->kobj);
-}
-
-/**
- * hdm_probe - probe function of USB device driver
- * @interface: Interface of the attached USB device
- * @id: Pointer to the USB ID table.
- *
- * This allocates and initializes the device instance, adds the new
- * entry to the internal list, scans the USB descriptors and registers
- * the interface with the core.
- * Additionally, the DCI objects are created and the hardware is sync'd.
- *
- * Return 0 on success. In case of an error a negative number is returned.
- */
-static int
-hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
-{
-	struct usb_host_interface *usb_iface_desc = interface->cur_altsetting;
-	struct usb_device *usb_dev = interface_to_usbdev(interface);
-	struct device *dev = &usb_dev->dev;
-	struct most_dev *mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
-	unsigned int i;
-	unsigned int num_endpoints;
-	struct most_channel_capability *tmp_cap;
-	struct usb_endpoint_descriptor *ep_desc;
-	int ret = 0;
-
-	if (!mdev)
-		goto exit_ENOMEM;
-
-	usb_set_intfdata(interface, mdev);
-	num_endpoints = usb_iface_desc->desc.bNumEndpoints;
-	mutex_init(&mdev->io_mutex);
-	INIT_WORK(&mdev->poll_work_obj, wq_netinfo);
-	setup_timer(&mdev->link_stat_timer, link_stat_timer_handler,
-		    (unsigned long)mdev);
-
-	mdev->usb_device = usb_dev;
-	mdev->link_stat_timer.expires = jiffies + (2 * HZ);
-
-	mdev->iface.mod = hdm_usb_fops.owner;
-	mdev->iface.interface = ITYPE_USB;
-	mdev->iface.configure = hdm_configure_channel;
-	mdev->iface.request_netinfo = hdm_request_netinfo;
-	mdev->iface.enqueue = hdm_enqueue;
-	mdev->iface.poison_channel = hdm_poison_channel;
-	mdev->iface.description = mdev->description;
-	mdev->iface.num_channels = num_endpoints;
-
-	snprintf(mdev->description, sizeof(mdev->description),
-		 "usb_device %d-%s:%d.%d",
-		 usb_dev->bus->busnum,
-		 usb_dev->devpath,
-		 usb_dev->config->desc.bConfigurationValue,
-		 usb_iface_desc->desc.bInterfaceNumber);
-
-	mdev->conf = kcalloc(num_endpoints, sizeof(*mdev->conf), GFP_KERNEL);
-	if (!mdev->conf)
-		goto exit_free;
-
-	mdev->cap = kcalloc(num_endpoints, sizeof(*mdev->cap), GFP_KERNEL);
-	if (!mdev->cap)
-		goto exit_free1;
-
-	mdev->iface.channel_vector = mdev->cap;
-	mdev->iface.priv = NULL;
-
-	mdev->ep_address =
-		kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL);
-	if (!mdev->ep_address)
-		goto exit_free2;
-
-	mdev->busy_urbs =
-		kcalloc(num_endpoints, sizeof(*mdev->busy_urbs), GFP_KERNEL);
-	if (!mdev->busy_urbs)
-		goto exit_free3;
-
-	tmp_cap = mdev->cap;
-	for (i = 0; i < num_endpoints; i++) {
-		ep_desc = &usb_iface_desc->endpoint[i].desc;
-		mdev->ep_address[i] = ep_desc->bEndpointAddress;
-		mdev->padding_active[i] = false;
-		mdev->is_channel_healthy[i] = true;
-
-		snprintf(&mdev->suffix[i][0], MAX_SUFFIX_LEN, "ep%02x",
-			 mdev->ep_address[i]);
-
-		tmp_cap->name_suffix = &mdev->suffix[i][0];
-		tmp_cap->buffer_size_packet = MAX_BUF_SIZE;
-		tmp_cap->buffer_size_streaming = MAX_BUF_SIZE;
-		tmp_cap->num_buffers_packet = BUF_CHAIN_SIZE;
-		tmp_cap->num_buffers_streaming = BUF_CHAIN_SIZE;
-		tmp_cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
-				     MOST_CH_ISOC | MOST_CH_SYNC;
-		if (usb_endpoint_dir_in(ep_desc))
-			tmp_cap->direction = MOST_CH_RX;
-		else
-			tmp_cap->direction = MOST_CH_TX;
-		tmp_cap++;
-		init_usb_anchor(&mdev->busy_urbs[i]);
-		spin_lock_init(&mdev->channel_lock[i]);
-	}
-	dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n",
-		   le16_to_cpu(usb_dev->descriptor.idVendor),
-		   le16_to_cpu(usb_dev->descriptor.idProduct),
-		   usb_dev->bus->busnum,
-		   usb_dev->devnum);
-
-	dev_notice(dev, "device path: /sys/bus/usb/devices/%d-%s:%d.%d\n",
-		   usb_dev->bus->busnum,
-		   usb_dev->devpath,
-		   usb_dev->config->desc.bConfigurationValue,
-		   usb_iface_desc->desc.bInterfaceNumber);
-
-	mdev->parent = most_register_interface(&mdev->iface);
-	if (IS_ERR(mdev->parent)) {
-		ret = PTR_ERR(mdev->parent);
-		goto exit_free4;
-	}
-
-	mutex_lock(&mdev->io_mutex);
-	if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 ||
-	    le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 ||
-	    le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) {
-		/* this increments the reference count of the instance
-		 * object of the core
-		 */
-		mdev->dci = create_most_dci_obj(mdev->parent);
-		if (!mdev->dci) {
-			mutex_unlock(&mdev->io_mutex);
-			most_deregister_interface(&mdev->iface);
-			ret = -ENOMEM;
-			goto exit_free4;
-		}
-
-		kobject_uevent(&mdev->dci->kobj, KOBJ_ADD);
-		mdev->dci->usb_device = mdev->usb_device;
-	}
-	mutex_unlock(&mdev->io_mutex);
-	return 0;
-
-exit_free4:
-	kfree(mdev->busy_urbs);
-exit_free3:
-	kfree(mdev->ep_address);
-exit_free2:
-	kfree(mdev->cap);
-exit_free1:
-	kfree(mdev->conf);
-exit_free:
-	kfree(mdev);
-exit_ENOMEM:
-	if (ret == 0 || ret == -ENOMEM) {
-		ret = -ENOMEM;
-		dev_err(dev, "out of memory\n");
-	}
-	return ret;
-}
-
-/**
- * hdm_disconnect - disconnect function of USB device driver
- * @interface: Interface of the attached USB device
- *
- * This deregisters the interface with the core, removes the kernel timer
- * and frees resources.
- *
- * Context: hub kernel thread
- */
-static void hdm_disconnect(struct usb_interface *interface)
-{
-	struct most_dev *mdev = usb_get_intfdata(interface);
-
-	mutex_lock(&mdev->io_mutex);
-	usb_set_intfdata(interface, NULL);
-	mdev->usb_device = NULL;
-	mutex_unlock(&mdev->io_mutex);
-
-	del_timer_sync(&mdev->link_stat_timer);
-	cancel_work_sync(&mdev->poll_work_obj);
-
-	destroy_most_dci_obj(mdev->dci);
-	most_deregister_interface(&mdev->iface);
-
-	kfree(mdev->busy_urbs);
-	kfree(mdev->cap);
-	kfree(mdev->conf);
-	kfree(mdev->ep_address);
-	kfree(mdev);
-}
-
-static struct usb_driver hdm_usb = {
-	.name = "hdm_usb",
-	.id_table = usbid,
-	.probe = hdm_probe,
-	.disconnect = hdm_disconnect,
-};
-
-module_usb_driver(hdm_usb);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
-MODULE_DESCRIPTION("HDM_4_USB");
diff --git a/drivers/staging/most/i2c/Kconfig b/drivers/staging/most/i2c/Kconfig
new file mode 100644
index 0000000..79d0ff2
--- /dev/null
+++ b/drivers/staging/most/i2c/Kconfig
@@ -0,0 +1,12 @@
+#
+# MOST I2C configuration
+#
+
+config MOST_I2C
+	tristate "I2C"
+	depends on I2C
+	---help---
+	  Say Y here if you want to connect via I2C to network tranceiver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called most_i2c.
diff --git a/drivers/staging/most/i2c/Makefile b/drivers/staging/most/i2c/Makefile
new file mode 100644
index 0000000..a7d094c
--- /dev/null
+++ b/drivers/staging/most/i2c/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_I2C) += most_i2c.o
+
+most_i2c-objs := i2c.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c
new file mode 100644
index 0000000..0a3e858
--- /dev/null
+++ b/drivers/staging/most/i2c/i2c.c
@@ -0,0 +1,423 @@
+/*
+ * i2c.c - Hardware Dependent Module for I2C Interface
+ *
+ * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+
+#include <most/core.h>
+
+enum { CH_RX, CH_TX, NUM_CHANNELS };
+
+#define MAX_BUFFERS_CONTROL 32
+#define MAX_BUF_SIZE_CONTROL 256
+
+/**
+ * list_first_mbo - get the first mbo from a list
+ * @ptr:	the list head to take the mbo from.
+ */
+#define list_first_mbo(ptr) \
+	list_first_entry(ptr, struct mbo, list)
+
+/* IRQ / Polling option */
+static bool polling_req;
+module_param(polling_req, bool, 0444);
+MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)");
+
+/* Polling Rate */
+static int scan_rate = 100;
+module_param(scan_rate, int, 0644);
+MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 100");
+
+struct hdm_i2c {
+	bool is_open[NUM_CHANNELS];
+	bool polling_mode;
+	struct most_interface most_iface;
+	struct most_channel_capability capabilities[NUM_CHANNELS];
+	struct i2c_client *client;
+	struct rx {
+		struct delayed_work dwork;
+		wait_queue_head_t waitq;
+		struct list_head list;
+		struct mutex list_mutex;
+	} rx;
+	char name[64];
+};
+
+#define to_hdm(iface) container_of(iface, struct hdm_i2c, most_iface)
+
+/**
+ * configure_channel - called from MOST core to configure a channel
+ * @iface: interface the channel belongs to
+ * @channel: channel to be configured
+ * @channel_config: structure that holds the configuration information
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * Receives configuration information from MOST core and initialize the
+ * corresponding channel.
+ */
+static int configure_channel(struct most_interface *most_iface,
+			     int ch_idx,
+			     struct most_channel_config *channel_config)
+{
+	struct hdm_i2c *dev = to_hdm(most_iface);
+
+	BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
+	BUG_ON(dev->is_open[ch_idx]);
+
+	if (channel_config->data_type != MOST_CH_CONTROL) {
+		pr_err("bad data type for channel %d\n", ch_idx);
+		return -EPERM;
+	}
+
+	if (channel_config->direction != dev->capabilities[ch_idx].direction) {
+		pr_err("bad direction for channel %d\n", ch_idx);
+		return -EPERM;
+	}
+
+	if ((channel_config->direction == MOST_CH_RX) && (dev->polling_mode)) {
+		schedule_delayed_work(&dev->rx.dwork,
+				      msecs_to_jiffies(MSEC_PER_SEC / 4));
+	}
+	dev->is_open[ch_idx] = true;
+
+	return 0;
+}
+
+/**
+ * enqueue - called from MOST core to enqueue a buffer for data transfer
+ * @iface: intended interface
+ * @channel: ID of the channel the buffer is intended for
+ * @mbo: pointer to the buffer object
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * Transmit the data over I2C if it is a "write" request or push the buffer into
+ * list if it is an "read" request
+ */
+static int enqueue(struct most_interface *most_iface,
+		   int ch_idx, struct mbo *mbo)
+{
+	struct hdm_i2c *dev = to_hdm(most_iface);
+	int ret;
+
+	BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
+	BUG_ON(!dev->is_open[ch_idx]);
+
+	if (ch_idx == CH_RX) {
+		/* RX */
+		mutex_lock(&dev->rx.list_mutex);
+		list_add_tail(&mbo->list, &dev->rx.list);
+		mutex_unlock(&dev->rx.list_mutex);
+		wake_up_interruptible(&dev->rx.waitq);
+	} else {
+		/* TX */
+		ret = i2c_master_send(dev->client, mbo->virt_address,
+				      mbo->buffer_length);
+		if (ret <= 0) {
+			mbo->processed_length = 0;
+			mbo->status = MBO_E_INVAL;
+		} else {
+			mbo->processed_length = mbo->buffer_length;
+			mbo->status = MBO_SUCCESS;
+		}
+		mbo->complete(mbo);
+	}
+
+	return 0;
+}
+
+/**
+ * poison_channel - called from MOST core to poison buffers of a channel
+ * @iface: pointer to the interface the channel to be poisoned belongs to
+ * @channel_id: corresponding channel ID
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * If channel direction is RX, complete the buffers in list with
+ * status MBO_E_CLOSE
+ */
+static int poison_channel(struct most_interface *most_iface,
+			  int ch_idx)
+{
+	struct hdm_i2c *dev = to_hdm(most_iface);
+	struct mbo *mbo;
+
+	BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
+	BUG_ON(!dev->is_open[ch_idx]);
+
+	dev->is_open[ch_idx] = false;
+
+	if (ch_idx == CH_RX) {
+		mutex_lock(&dev->rx.list_mutex);
+		while (!list_empty(&dev->rx.list)) {
+			mbo = list_first_mbo(&dev->rx.list);
+			list_del(&mbo->list);
+			mutex_unlock(&dev->rx.list_mutex);
+
+			mbo->processed_length = 0;
+			mbo->status = MBO_E_CLOSE;
+			mbo->complete(mbo);
+
+			mutex_lock(&dev->rx.list_mutex);
+		}
+		mutex_unlock(&dev->rx.list_mutex);
+		wake_up_interruptible(&dev->rx.waitq);
+	}
+
+	return 0;
+}
+
+static void do_rx_work(struct hdm_i2c *dev)
+{
+	struct mbo *mbo;
+	unsigned char msg[MAX_BUF_SIZE_CONTROL];
+	int ret, ch_idx = CH_RX;
+	u16 pml, data_size;
+
+	/* Read PML (2 bytes) */
+	ret = i2c_master_recv(dev->client, msg, 2);
+	if (ret <= 0) {
+		pr_err("Failed to receive PML\n");
+		return;
+	}
+
+	pml = (msg[0] << 8) | msg[1];
+	if (!pml)
+		return;
+
+	data_size = pml + 2;
+
+	/* Read the whole message, including PML */
+	ret = i2c_master_recv(dev->client, msg, data_size);
+	if (ret <= 0) {
+		pr_err("Failed to receive a Port Message\n");
+		return;
+	}
+
+	for (;;) {
+		/* Conditions to wait for: poisoned channel or free buffer
+		 * available for reading
+		 */
+		if (wait_event_interruptible(dev->rx.waitq,
+					     !dev->is_open[ch_idx] ||
+					     !list_empty(&dev->rx.list))) {
+			pr_err("wait_event_interruptible() failed\n");
+			return;
+		}
+
+		if (!dev->is_open[ch_idx])
+			return;
+
+		mutex_lock(&dev->rx.list_mutex);
+
+		/* list may be empty if poison or remove is called */
+		if (!list_empty(&dev->rx.list))
+			break;
+
+		mutex_unlock(&dev->rx.list_mutex);
+	}
+
+	mbo = list_first_mbo(&dev->rx.list);
+	list_del(&mbo->list);
+	mutex_unlock(&dev->rx.list_mutex);
+
+	mbo->processed_length = min(data_size, mbo->buffer_length);
+	memcpy(mbo->virt_address, msg, mbo->processed_length);
+	mbo->status = MBO_SUCCESS;
+	mbo->complete(mbo);
+}
+
+/**
+ * pending_rx_work - Read pending messages through I2C
+ * @work: definition of this work item
+ *
+ * Invoked by the Interrupt Service Routine, most_irq_handler()
+ */
+static void pending_rx_work(struct work_struct *work)
+{
+	struct hdm_i2c *dev = container_of(work, struct hdm_i2c, rx.dwork.work);
+
+	do_rx_work(dev);
+
+	if (dev->polling_mode) {
+		if (dev->is_open[CH_RX])
+			schedule_delayed_work(&dev->rx.dwork,
+					      msecs_to_jiffies(MSEC_PER_SEC
+							       / scan_rate));
+	} else {
+		enable_irq(dev->client->irq);
+	}
+}
+
+/*
+ * most_irq_handler - Interrupt Service Routine
+ * @irq: irq number
+ * @_dev: private data
+ *
+ * Schedules a delayed work
+ *
+ * By default the interrupt line behavior is Active Low. Once an interrupt is
+ * generated by the device, until driver clears the interrupt (by reading
+ * the PMP message), device keeps the interrupt line in low state. Since i2c
+ * read is done in work queue, the interrupt line must be disabled temporarily
+ * to avoid ISR being called repeatedly. Re-enable the interrupt in workqueue,
+ * after reading the message.
+ *
+ * Note: If we use the interrupt line in Falling edge mode, there is a
+ * possibility to miss interrupts when ISR is getting executed.
+ *
+ */
+static irqreturn_t most_irq_handler(int irq, void *_dev)
+{
+	struct hdm_i2c *dev = _dev;
+
+	disable_irq_nosync(irq);
+
+	schedule_delayed_work(&dev->rx.dwork, 0);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * i2c_probe - i2c probe handler
+ * @client: i2c client device structure
+ * @id: i2c client device id
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * Register the i2c client device as a MOST interface
+ */
+static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct hdm_i2c *dev;
+	int ret, i;
+	struct kobject *kobj;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	/* ID format: i2c-<bus>-<address> */
+	snprintf(dev->name, sizeof(dev->name), "i2c-%d-%04x",
+		 client->adapter->nr, client->addr);
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		dev->is_open[i] = false;
+		dev->capabilities[i].data_type = MOST_CH_CONTROL;
+		dev->capabilities[i].num_buffers_packet = MAX_BUFFERS_CONTROL;
+		dev->capabilities[i].buffer_size_packet = MAX_BUF_SIZE_CONTROL;
+	}
+	dev->capabilities[CH_RX].direction = MOST_CH_RX;
+	dev->capabilities[CH_RX].name_suffix = "rx";
+	dev->capabilities[CH_TX].direction = MOST_CH_TX;
+	dev->capabilities[CH_TX].name_suffix = "tx";
+
+	dev->most_iface.interface = ITYPE_I2C;
+	dev->most_iface.description = dev->name;
+	dev->most_iface.num_channels = NUM_CHANNELS;
+	dev->most_iface.channel_vector = dev->capabilities;
+	dev->most_iface.configure = configure_channel;
+	dev->most_iface.enqueue = enqueue;
+	dev->most_iface.poison_channel = poison_channel;
+
+	INIT_LIST_HEAD(&dev->rx.list);
+	mutex_init(&dev->rx.list_mutex);
+	init_waitqueue_head(&dev->rx.waitq);
+
+	INIT_DELAYED_WORK(&dev->rx.dwork, pending_rx_work);
+
+	dev->client = client;
+	i2c_set_clientdata(client, dev);
+
+	kobj = most_register_interface(&dev->most_iface);
+	if (IS_ERR(kobj)) {
+		pr_err("Failed to register i2c as a MOST interface\n");
+		kfree(dev);
+		return PTR_ERR(kobj);
+	}
+
+	dev->polling_mode = polling_req || client->irq <= 0;
+	if (!dev->polling_mode) {
+		pr_info("Requesting IRQ: %d\n", client->irq);
+		ret = request_irq(client->irq, most_irq_handler, 0,
+				  client->name, dev);
+		if (ret) {
+			pr_info("IRQ request failed: %d, falling back to polling\n",
+				ret);
+			dev->polling_mode = true;
+		}
+	}
+
+	if (dev->polling_mode)
+		pr_info("Using polling at rate: %d times/sec\n", scan_rate);
+
+	return 0;
+}
+
+/*
+ * i2c_remove - i2c remove handler
+ * @client: i2c client device structure
+ *
+ * Return 0 on success.
+ *
+ * Unregister the i2c client device as a MOST interface
+ */
+static int i2c_remove(struct i2c_client *client)
+{
+	struct hdm_i2c *dev = i2c_get_clientdata(client);
+	int i;
+
+	if (!dev->polling_mode)
+		free_irq(client->irq, dev);
+
+	most_deregister_interface(&dev->most_iface);
+
+	for (i = 0 ; i < NUM_CHANNELS; i++)
+		if (dev->is_open[i])
+			poison_channel(&dev->most_iface, i);
+	cancel_delayed_work_sync(&dev->rx.dwork);
+	kfree(dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id i2c_id[] = {
+	{ "most_i2c", 0 },
+	{ }, /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(i2c, i2c_id);
+
+static struct i2c_driver i2c_driver = {
+	.driver = {
+		.name = "hdm_i2c",
+	},
+	.probe = i2c_probe,
+	.remove = i2c_remove,
+	.id_table = i2c_id,
+};
+
+module_i2c_driver(i2c_driver);
+
+MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_DESCRIPTION("I2C Hardware Dependent Module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/mostcore/Kconfig b/drivers/staging/most/mostcore/Kconfig
deleted file mode 100644
index 4717254..0000000
--- a/drivers/staging/most/mostcore/Kconfig
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# MOSTCore configuration
-#
-
-config MOSTCORE
-	tristate "MOST Core"
-	depends on HAS_DMA
-
-	---help---
-	  Say Y here if you want to enable MOST support.
-	  This device driver needs at least an additional AIM and HDM to work.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called mostcore.
diff --git a/drivers/staging/most/mostcore/Makefile b/drivers/staging/most/mostcore/Makefile
deleted file mode 100644
index a078f01..0000000
--- a/drivers/staging/most/mostcore/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_MOSTCORE) += mostcore.o
-
-mostcore-objs := core.o
diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c
deleted file mode 100644
index 069269d..0000000
--- a/drivers/staging/most/mostcore/core.c
+++ /dev/null
@@ -1,1949 +0,0 @@
-/*
- * core.c - Implementation of core module of MOST Linux driver stack
- *
- * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/poll.h>
-#include <linux/wait.h>
-#include <linux/kobject.h>
-#include <linux/mutex.h>
-#include <linux/completion.h>
-#include <linux/sysfs.h>
-#include <linux/kthread.h>
-#include <linux/dma-mapping.h>
-#include <linux/idr.h>
-#include "mostcore.h"
-
-#define MAX_CHANNELS	64
-#define STRING_SIZE	80
-
-static struct class *most_class;
-static struct device *core_dev;
-static struct ida mdev_id;
-static int dummy_num_buffers;
-
-struct most_c_aim_obj {
-	struct most_aim *ptr;
-	int refs;
-	int num_buffers;
-};
-
-struct most_c_obj {
-	struct kobject kobj;
-	struct completion cleanup;
-	atomic_t mbo_ref;
-	atomic_t mbo_nq_level;
-	u16 channel_id;
-	bool is_poisoned;
-	struct mutex start_mutex;
-	struct mutex nq_mutex; /* nq thread synchronization */
-	int is_starving;
-	struct most_interface *iface;
-	struct most_inst_obj *inst;
-	struct most_channel_config cfg;
-	bool keep_mbo;
-	bool enqueue_halt;
-	struct list_head fifo;
-	spinlock_t fifo_lock;
-	struct list_head halt_fifo;
-	struct list_head list;
-	struct most_c_aim_obj aim0;
-	struct most_c_aim_obj aim1;
-	struct list_head trash_fifo;
-	struct task_struct *hdm_enqueue_task;
-	wait_queue_head_t hdm_fifo_wq;
-};
-
-#define to_c_obj(d) container_of(d, struct most_c_obj, kobj)
-
-struct most_inst_obj {
-	int dev_id;
-	struct most_interface *iface;
-	struct list_head channel_list;
-	struct most_c_obj *channel[MAX_CHANNELS];
-	struct kobject kobj;
-	struct list_head list;
-};
-
-static const struct {
-	int most_ch_data_type;
-	const char *name;
-} ch_data_type[] = {
-	{ MOST_CH_CONTROL, "control\n" },
-	{ MOST_CH_ASYNC, "async\n" },
-	{ MOST_CH_SYNC, "sync\n" },
-	{ MOST_CH_ISOC, "isoc\n"},
-	{ MOST_CH_ISOC, "isoc_avp\n"},
-};
-
-#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj)
-
-/**
- * list_pop_mbo - retrieves the first MBO of the list and removes it
- * @ptr: the list head to grab the MBO from.
- */
-#define list_pop_mbo(ptr)						\
-({									\
-	struct mbo *_mbo = list_first_entry(ptr, struct mbo, list);	\
-	list_del(&_mbo->list);						\
-	_mbo;								\
-})
-
-/*		     ___	     ___
- *		     ___C H A N N E L___
- */
-
-/**
- * struct most_c_attr - to access the attributes of a channel object
- * @attr: attributes of a channel
- * @show: pointer to the show function
- * @store: pointer to the store function
- */
-struct most_c_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct most_c_obj *d,
-			struct most_c_attr *attr,
-			char *buf);
-	ssize_t (*store)(struct most_c_obj *d,
-			 struct most_c_attr *attr,
-			 const char *buf,
-			 size_t count);
-};
-
-#define to_channel_attr(a) container_of(a, struct most_c_attr, attr)
-
-/**
- * channel_attr_show - show function of channel object
- * @kobj: pointer to its kobject
- * @attr: pointer to its attributes
- * @buf: buffer
- */
-static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr,
-				 char *buf)
-{
-	struct most_c_attr *channel_attr = to_channel_attr(attr);
-	struct most_c_obj *c_obj = to_c_obj(kobj);
-
-	if (!channel_attr->show)
-		return -EIO;
-
-	return channel_attr->show(c_obj, channel_attr, buf);
-}
-
-/**
- * channel_attr_store - store function of channel object
- * @kobj: pointer to its kobject
- * @attr: pointer to its attributes
- * @buf: buffer
- * @len: length of buffer
- */
-static ssize_t channel_attr_store(struct kobject *kobj,
-				  struct attribute *attr,
-				  const char *buf,
-				  size_t len)
-{
-	struct most_c_attr *channel_attr = to_channel_attr(attr);
-	struct most_c_obj *c_obj = to_c_obj(kobj);
-
-	if (!channel_attr->store)
-		return -EIO;
-	return channel_attr->store(c_obj, channel_attr, buf, len);
-}
-
-static const struct sysfs_ops most_channel_sysfs_ops = {
-	.show = channel_attr_show,
-	.store = channel_attr_store,
-};
-
-/**
- * most_free_mbo_coherent - free an MBO and its coherent buffer
- * @mbo: buffer to be released
- *
- */
-static void most_free_mbo_coherent(struct mbo *mbo)
-{
-	struct most_c_obj *c = mbo->context;
-	u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
-
-	dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address,
-			  mbo->bus_address);
-	kfree(mbo);
-	if (atomic_sub_and_test(1, &c->mbo_ref))
-		complete(&c->cleanup);
-}
-
-/**
- * flush_channel_fifos - clear the channel fifos
- * @c: pointer to channel object
- */
-static void flush_channel_fifos(struct most_c_obj *c)
-{
-	unsigned long flags, hf_flags;
-	struct mbo *mbo, *tmp;
-
-	if (list_empty(&c->fifo) && list_empty(&c->halt_fifo))
-		return;
-
-	spin_lock_irqsave(&c->fifo_lock, flags);
-	list_for_each_entry_safe(mbo, tmp, &c->fifo, list) {
-		list_del(&mbo->list);
-		spin_unlock_irqrestore(&c->fifo_lock, flags);
-		most_free_mbo_coherent(mbo);
-		spin_lock_irqsave(&c->fifo_lock, flags);
-	}
-	spin_unlock_irqrestore(&c->fifo_lock, flags);
-
-	spin_lock_irqsave(&c->fifo_lock, hf_flags);
-	list_for_each_entry_safe(mbo, tmp, &c->halt_fifo, list) {
-		list_del(&mbo->list);
-		spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
-		most_free_mbo_coherent(mbo);
-		spin_lock_irqsave(&c->fifo_lock, hf_flags);
-	}
-	spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
-
-	if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo))))
-		pr_info("WARN: fifo | trash fifo not empty\n");
-}
-
-/**
- * flush_trash_fifo - clear the trash fifo
- * @c: pointer to channel object
- */
-static int flush_trash_fifo(struct most_c_obj *c)
-{
-	struct mbo *mbo, *tmp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&c->fifo_lock, flags);
-	list_for_each_entry_safe(mbo, tmp, &c->trash_fifo, list) {
-		list_del(&mbo->list);
-		spin_unlock_irqrestore(&c->fifo_lock, flags);
-		most_free_mbo_coherent(mbo);
-		spin_lock_irqsave(&c->fifo_lock, flags);
-	}
-	spin_unlock_irqrestore(&c->fifo_lock, flags);
-	return 0;
-}
-
-/**
- * most_channel_release - release function of channel object
- * @kobj: pointer to channel's kobject
- */
-static void most_channel_release(struct kobject *kobj)
-{
-	struct most_c_obj *c = to_c_obj(kobj);
-
-	kfree(c);
-}
-
-static ssize_t available_directions_show(struct most_c_obj *c,
-					 struct most_c_attr *attr,
-					 char *buf)
-{
-	unsigned int i = c->channel_id;
-
-	strcpy(buf, "");
-	if (c->iface->channel_vector[i].direction & MOST_CH_RX)
-		strcat(buf, "rx ");
-	if (c->iface->channel_vector[i].direction & MOST_CH_TX)
-		strcat(buf, "tx ");
-	strcat(buf, "\n");
-	return strlen(buf);
-}
-
-static ssize_t available_datatypes_show(struct most_c_obj *c,
-					struct most_c_attr *attr,
-					char *buf)
-{
-	unsigned int i = c->channel_id;
-
-	strcpy(buf, "");
-	if (c->iface->channel_vector[i].data_type & MOST_CH_CONTROL)
-		strcat(buf, "control ");
-	if (c->iface->channel_vector[i].data_type & MOST_CH_ASYNC)
-		strcat(buf, "async ");
-	if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC)
-		strcat(buf, "sync ");
-	if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC)
-		strcat(buf, "isoc ");
-	strcat(buf, "\n");
-	return strlen(buf);
-}
-
-static ssize_t number_of_packet_buffers_show(struct most_c_obj *c,
-					     struct most_c_attr *attr,
-					     char *buf)
-{
-	unsigned int i = c->channel_id;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			c->iface->channel_vector[i].num_buffers_packet);
-}
-
-static ssize_t number_of_stream_buffers_show(struct most_c_obj *c,
-					     struct most_c_attr *attr,
-					     char *buf)
-{
-	unsigned int i = c->channel_id;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			c->iface->channel_vector[i].num_buffers_streaming);
-}
-
-static ssize_t size_of_packet_buffer_show(struct most_c_obj *c,
-					  struct most_c_attr *attr,
-					  char *buf)
-{
-	unsigned int i = c->channel_id;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			c->iface->channel_vector[i].buffer_size_packet);
-}
-
-static ssize_t size_of_stream_buffer_show(struct most_c_obj *c,
-					  struct most_c_attr *attr,
-					  char *buf)
-{
-	unsigned int i = c->channel_id;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			c->iface->channel_vector[i].buffer_size_streaming);
-}
-
-static ssize_t channel_starving_show(struct most_c_obj *c,
-				     struct most_c_attr *attr,
-				     char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving);
-}
-
-static ssize_t set_number_of_buffers_show(struct most_c_obj *c,
-					  struct most_c_attr *attr,
-					  char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers);
-}
-
-static ssize_t set_number_of_buffers_store(struct most_c_obj *c,
-					   struct most_c_attr *attr,
-					   const char *buf,
-					   size_t count)
-{
-	int ret = kstrtou16(buf, 0, &c->cfg.num_buffers);
-
-	if (ret)
-		return ret;
-	return count;
-}
-
-static ssize_t set_buffer_size_show(struct most_c_obj *c,
-				    struct most_c_attr *attr,
-				    char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size);
-}
-
-static ssize_t set_buffer_size_store(struct most_c_obj *c,
-				     struct most_c_attr *attr,
-				     const char *buf,
-				     size_t count)
-{
-	int ret = kstrtou16(buf, 0, &c->cfg.buffer_size);
-
-	if (ret)
-		return ret;
-	return count;
-}
-
-static ssize_t set_direction_show(struct most_c_obj *c,
-				  struct most_c_attr *attr,
-				  char *buf)
-{
-	if (c->cfg.direction & MOST_CH_TX)
-		return snprintf(buf, PAGE_SIZE, "tx\n");
-	else if (c->cfg.direction & MOST_CH_RX)
-		return snprintf(buf, PAGE_SIZE, "rx\n");
-	return snprintf(buf, PAGE_SIZE, "unconfigured\n");
-}
-
-static ssize_t set_direction_store(struct most_c_obj *c,
-				   struct most_c_attr *attr,
-				   const char *buf,
-				   size_t count)
-{
-	if (!strcmp(buf, "dir_rx\n")) {
-		c->cfg.direction = MOST_CH_RX;
-	} else if (!strcmp(buf, "rx\n")) {
-		c->cfg.direction = MOST_CH_RX;
-	} else if (!strcmp(buf, "dir_tx\n")) {
-		c->cfg.direction = MOST_CH_TX;
-	} else if (!strcmp(buf, "tx\n")) {
-		c->cfg.direction = MOST_CH_TX;
-	} else {
-		pr_info("WARN: invalid attribute settings\n");
-		return -EINVAL;
-	}
-	return count;
-}
-
-static ssize_t set_datatype_show(struct most_c_obj *c,
-				 struct most_c_attr *attr,
-				 char *buf)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
-		if (c->cfg.data_type & ch_data_type[i].most_ch_data_type)
-			return snprintf(buf, PAGE_SIZE, ch_data_type[i].name);
-	}
-	return snprintf(buf, PAGE_SIZE, "unconfigured\n");
-}
-
-static ssize_t set_datatype_store(struct most_c_obj *c,
-				  struct most_c_attr *attr,
-				  const char *buf,
-				  size_t count)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
-		if (!strcmp(buf, ch_data_type[i].name)) {
-			c->cfg.data_type = ch_data_type[i].most_ch_data_type;
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(ch_data_type)) {
-		pr_info("WARN: invalid attribute settings\n");
-		return -EINVAL;
-	}
-	return count;
-}
-
-static ssize_t set_subbuffer_size_show(struct most_c_obj *c,
-				       struct most_c_attr *attr,
-				       char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size);
-}
-
-static ssize_t set_subbuffer_size_store(struct most_c_obj *c,
-					struct most_c_attr *attr,
-					const char *buf,
-					size_t count)
-{
-	int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size);
-
-	if (ret)
-		return ret;
-	return count;
-}
-
-static ssize_t set_packets_per_xact_show(struct most_c_obj *c,
-					 struct most_c_attr *attr,
-					 char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact);
-}
-
-static ssize_t set_packets_per_xact_store(struct most_c_obj *c,
-					  struct most_c_attr *attr,
-					  const char *buf,
-					  size_t count)
-{
-	int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact);
-
-	if (ret)
-		return ret;
-	return count;
-}
-
-static struct most_c_attr most_c_attrs[] = {
-	__ATTR_RO(available_directions),
-	__ATTR_RO(available_datatypes),
-	__ATTR_RO(number_of_packet_buffers),
-	__ATTR_RO(number_of_stream_buffers),
-	__ATTR_RO(size_of_stream_buffer),
-	__ATTR_RO(size_of_packet_buffer),
-	__ATTR_RO(channel_starving),
-	__ATTR_RW(set_buffer_size),
-	__ATTR_RW(set_number_of_buffers),
-	__ATTR_RW(set_direction),
-	__ATTR_RW(set_datatype),
-	__ATTR_RW(set_subbuffer_size),
-	__ATTR_RW(set_packets_per_xact),
-};
-
-/**
- * most_channel_def_attrs - array of default attributes of channel object
- */
-static struct attribute *most_channel_def_attrs[] = {
-	&most_c_attrs[0].attr,
-	&most_c_attrs[1].attr,
-	&most_c_attrs[2].attr,
-	&most_c_attrs[3].attr,
-	&most_c_attrs[4].attr,
-	&most_c_attrs[5].attr,
-	&most_c_attrs[6].attr,
-	&most_c_attrs[7].attr,
-	&most_c_attrs[8].attr,
-	&most_c_attrs[9].attr,
-	&most_c_attrs[10].attr,
-	&most_c_attrs[11].attr,
-	&most_c_attrs[12].attr,
-	NULL,
-};
-
-static struct kobj_type most_channel_ktype = {
-	.sysfs_ops = &most_channel_sysfs_ops,
-	.release = most_channel_release,
-	.default_attrs = most_channel_def_attrs,
-};
-
-static struct kset *most_channel_kset;
-
-/**
- * create_most_c_obj - allocates a channel object
- * @name: name of the channel object
- * @parent: parent kobject
- *
- * This create a channel object and registers it with sysfs.
- * Returns a pointer to the object or NULL when something went wrong.
- */
-static struct most_c_obj *
-create_most_c_obj(const char *name, struct kobject *parent)
-{
-	struct most_c_obj *c;
-	int retval;
-
-	c = kzalloc(sizeof(*c), GFP_KERNEL);
-	if (!c)
-		return NULL;
-	c->kobj.kset = most_channel_kset;
-	retval = kobject_init_and_add(&c->kobj, &most_channel_ktype, parent,
-				      "%s", name);
-	if (retval) {
-		kobject_put(&c->kobj);
-		return NULL;
-	}
-	kobject_uevent(&c->kobj, KOBJ_ADD);
-	return c;
-}
-
-/*		     ___	       ___
- *		     ___I N S T A N C E___
- */
-
-static struct list_head instance_list;
-
-/**
- * struct most_inst_attribute - to access the attributes of instance object
- * @attr: attributes of an instance
- * @show: pointer to the show function
- * @store: pointer to the store function
- */
-struct most_inst_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct most_inst_obj *d,
-			struct most_inst_attribute *attr,
-			char *buf);
-	ssize_t (*store)(struct most_inst_obj *d,
-			 struct most_inst_attribute *attr,
-			 const char *buf,
-			 size_t count);
-};
-
-#define to_instance_attr(a) \
-	container_of(a, struct most_inst_attribute, attr)
-
-/**
- * instance_attr_show - show function for an instance object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- */
-static ssize_t instance_attr_show(struct kobject *kobj,
-				  struct attribute *attr,
-				  char *buf)
-{
-	struct most_inst_attribute *instance_attr;
-	struct most_inst_obj *instance_obj;
-
-	instance_attr = to_instance_attr(attr);
-	instance_obj = to_inst_obj(kobj);
-
-	if (!instance_attr->show)
-		return -EIO;
-
-	return instance_attr->show(instance_obj, instance_attr, buf);
-}
-
-/**
- * instance_attr_store - store function for an instance object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- * @len: length of buffer
- */
-static ssize_t instance_attr_store(struct kobject *kobj,
-				   struct attribute *attr,
-				   const char *buf,
-				   size_t len)
-{
-	struct most_inst_attribute *instance_attr;
-	struct most_inst_obj *instance_obj;
-
-	instance_attr = to_instance_attr(attr);
-	instance_obj = to_inst_obj(kobj);
-
-	if (!instance_attr->store)
-		return -EIO;
-
-	return instance_attr->store(instance_obj, instance_attr, buf, len);
-}
-
-static const struct sysfs_ops most_inst_sysfs_ops = {
-	.show = instance_attr_show,
-	.store = instance_attr_store,
-};
-
-/**
- * most_inst_release - release function for instance object
- * @kobj: pointer to instance's kobject
- *
- * This frees the allocated memory for the instance object
- */
-static void most_inst_release(struct kobject *kobj)
-{
-	struct most_inst_obj *inst = to_inst_obj(kobj);
-
-	kfree(inst);
-}
-
-static ssize_t description_show(struct most_inst_obj *instance_obj,
-				struct most_inst_attribute *attr,
-				char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%s\n",
-			instance_obj->iface->description);
-}
-
-static ssize_t interface_show(struct most_inst_obj *instance_obj,
-			      struct most_inst_attribute *attr,
-			      char *buf)
-{
-	switch (instance_obj->iface->interface) {
-	case ITYPE_LOOPBACK:
-		return snprintf(buf, PAGE_SIZE, "loopback\n");
-	case ITYPE_I2C:
-		return snprintf(buf, PAGE_SIZE, "i2c\n");
-	case ITYPE_I2S:
-		return snprintf(buf, PAGE_SIZE, "i2s\n");
-	case ITYPE_TSI:
-		return snprintf(buf, PAGE_SIZE, "tsi\n");
-	case ITYPE_HBI:
-		return snprintf(buf, PAGE_SIZE, "hbi\n");
-	case ITYPE_MEDIALB_DIM:
-		return snprintf(buf, PAGE_SIZE, "mlb_dim\n");
-	case ITYPE_MEDIALB_DIM2:
-		return snprintf(buf, PAGE_SIZE, "mlb_dim2\n");
-	case ITYPE_USB:
-		return snprintf(buf, PAGE_SIZE, "usb\n");
-	case ITYPE_PCIE:
-		return snprintf(buf, PAGE_SIZE, "pcie\n");
-	}
-	return snprintf(buf, PAGE_SIZE, "unknown\n");
-}
-
-static struct most_inst_attribute most_inst_attr_description =
-	__ATTR_RO(description);
-
-static struct most_inst_attribute most_inst_attr_interface =
-	__ATTR_RO(interface);
-
-static struct attribute *most_inst_def_attrs[] = {
-	&most_inst_attr_description.attr,
-	&most_inst_attr_interface.attr,
-	NULL,
-};
-
-static struct kobj_type most_inst_ktype = {
-	.sysfs_ops = &most_inst_sysfs_ops,
-	.release = most_inst_release,
-	.default_attrs = most_inst_def_attrs,
-};
-
-static struct kset *most_inst_kset;
-
-/**
- * create_most_inst_obj - creates an instance object
- * @name: name of the object to be created
- *
- * This allocates memory for an instance structure, assigns the proper kset
- * and registers it with sysfs.
- *
- * Returns a pointer to the instance object or NULL when something went wrong.
- */
-static struct most_inst_obj *create_most_inst_obj(const char *name)
-{
-	struct most_inst_obj *inst;
-	int retval;
-
-	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
-	if (!inst)
-		return NULL;
-	inst->kobj.kset = most_inst_kset;
-	retval = kobject_init_and_add(&inst->kobj, &most_inst_ktype, NULL,
-				      "%s", name);
-	if (retval) {
-		kobject_put(&inst->kobj);
-		return NULL;
-	}
-	kobject_uevent(&inst->kobj, KOBJ_ADD);
-	return inst;
-}
-
-/**
- * destroy_most_inst_obj - MOST instance release function
- * @inst: pointer to the instance object
- *
- * This decrements the reference counter of the instance object.
- * If the reference count turns zero, its release function is called
- */
-static void destroy_most_inst_obj(struct most_inst_obj *inst)
-{
-	struct most_c_obj *c, *tmp;
-
-	list_for_each_entry_safe(c, tmp, &inst->channel_list, list) {
-		flush_trash_fifo(c);
-		flush_channel_fifos(c);
-		kobject_put(&c->kobj);
-	}
-	kobject_put(&inst->kobj);
-}
-
-/*		     ___     ___
- *		     ___A I M___
- */
-struct most_aim_obj {
-	struct kobject kobj;
-	struct list_head list;
-	struct most_aim *driver;
-};
-
-#define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj)
-
-static struct list_head aim_list;
-
-/**
- * struct most_aim_attribute - to access the attributes of AIM object
- * @attr: attributes of an AIM
- * @show: pointer to the show function
- * @store: pointer to the store function
- */
-struct most_aim_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct most_aim_obj *d,
-			struct most_aim_attribute *attr,
-			char *buf);
-	ssize_t (*store)(struct most_aim_obj *d,
-			 struct most_aim_attribute *attr,
-			 const char *buf,
-			 size_t count);
-};
-
-#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr)
-
-/**
- * aim_attr_show - show function of an AIM object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- */
-static ssize_t aim_attr_show(struct kobject *kobj,
-			     struct attribute *attr,
-			     char *buf)
-{
-	struct most_aim_attribute *aim_attr;
-	struct most_aim_obj *aim_obj;
-
-	aim_attr = to_aim_attr(attr);
-	aim_obj = to_aim_obj(kobj);
-
-	if (!aim_attr->show)
-		return -EIO;
-
-	return aim_attr->show(aim_obj, aim_attr, buf);
-}
-
-/**
- * aim_attr_store - store function of an AIM object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- * @len: length of buffer
- */
-static ssize_t aim_attr_store(struct kobject *kobj,
-			      struct attribute *attr,
-			      const char *buf,
-			      size_t len)
-{
-	struct most_aim_attribute *aim_attr;
-	struct most_aim_obj *aim_obj;
-
-	aim_attr = to_aim_attr(attr);
-	aim_obj = to_aim_obj(kobj);
-
-	if (!aim_attr->store)
-		return -EIO;
-	return aim_attr->store(aim_obj, aim_attr, buf, len);
-}
-
-static const struct sysfs_ops most_aim_sysfs_ops = {
-	.show = aim_attr_show,
-	.store = aim_attr_store,
-};
-
-/**
- * most_aim_release - AIM release function
- * @kobj: pointer to AIM's kobject
- */
-static void most_aim_release(struct kobject *kobj)
-{
-	struct most_aim_obj *aim_obj = to_aim_obj(kobj);
-
-	kfree(aim_obj);
-}
-
-static ssize_t links_show(struct most_aim_obj *aim_obj,
-			  struct most_aim_attribute *attr,
-			  char *buf)
-{
-	struct most_c_obj *c;
-	struct most_inst_obj *i;
-	int offs = 0;
-
-	list_for_each_entry(i, &instance_list, list) {
-		list_for_each_entry(c, &i->channel_list, list) {
-			if (c->aim0.ptr == aim_obj->driver ||
-			    c->aim1.ptr == aim_obj->driver) {
-				offs += snprintf(buf + offs, PAGE_SIZE - offs,
-						 "%s:%s\n",
-						 kobject_name(&i->kobj),
-						 kobject_name(&c->kobj));
-			}
-		}
-	}
-
-	return offs;
-}
-
-/**
- * split_string - parses and changes string in the buffer buf and
- * splits it into two mandatory and one optional substrings.
- *
- * @buf: complete string from attribute 'add_channel'
- * @a: address of pointer to 1st substring (=instance name)
- * @b: address of pointer to 2nd substring (=channel name)
- * @c: optional address of pointer to 3rd substring (=user defined name)
- *
- * Examples:
- *
- * Input: "mdev0:ch6:my_channel\n" or
- *        "mdev0:ch6:my_channel"
- *
- * Output: *a -> "mdev0", *b -> "ch6", *c -> "my_channel"
- *
- * Input: "mdev1:ep81\n"
- * Output: *a -> "mdev1", *b -> "ep81", *c -> ""
- *
- * Input: "mdev1:ep81"
- * Output: *a -> "mdev1", *b -> "ep81", *c == NULL
- */
-static int split_string(char *buf, char **a, char **b, char **c)
-{
-	*a = strsep(&buf, ":");
-	if (!*a)
-		return -EIO;
-
-	*b = strsep(&buf, ":\n");
-	if (!*b)
-		return -EIO;
-
-	if (c)
-		*c = strsep(&buf, ":\n");
-
-	return 0;
-}
-
-/**
- * get_channel_by_name - get pointer to channel object
- * @mdev: name of the device instance
- * @mdev_ch: name of the respective channel
- *
- * This retrieves the pointer to a channel object.
- */
-static struct
-most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
-{
-	struct most_c_obj *c, *tmp;
-	struct most_inst_obj *i, *i_tmp;
-	int found = 0;
-
-	list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
-		if (!strcmp(kobject_name(&i->kobj), mdev)) {
-			found++;
-			break;
-		}
-	}
-	if (unlikely(!found))
-		return ERR_PTR(-EIO);
-
-	list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
-		if (!strcmp(kobject_name(&c->kobj), mdev_ch)) {
-			found++;
-			break;
-		}
-	}
-	if (unlikely(found < 2))
-		return ERR_PTR(-EIO);
-	return c;
-}
-
-/**
- * add_link_store - store() function for add_link attribute
- * @aim_obj: pointer to AIM object
- * @attr: its attributes
- * @buf: buffer
- * @len: buffer length
- *
- * This parses the string given by buf and splits it into
- * three substrings. Note: third substring is optional. In case a cdev
- * AIM is loaded the optional 3rd substring will make up the name of
- * device node in the /dev directory. If omitted, the device node will
- * inherit the channel's name within sysfs.
- *
- * Searches for a pair of device and channel and probes the AIM
- *
- * Example:
- * (1) echo "mdev0:ch6:my_rxchannel" >add_link
- * (2) echo "mdev1:ep81" >add_link
- *
- * (1) would create the device node /dev/my_rxchannel
- * (2) would create the device node /dev/mdev1-ep81
- */
-static ssize_t add_link_store(struct most_aim_obj *aim_obj,
-			      struct most_aim_attribute *attr,
-			      const char *buf,
-			      size_t len)
-{
-	struct most_c_obj *c;
-	struct most_aim **aim_ptr;
-	char buffer[STRING_SIZE];
-	char *mdev;
-	char *mdev_ch;
-	char *mdev_devnod;
-	char devnod_buf[STRING_SIZE];
-	int ret;
-	size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
-
-	strlcpy(buffer, buf, max_len);
-
-	ret = split_string(buffer, &mdev, &mdev_ch, &mdev_devnod);
-	if (ret)
-		return ret;
-
-	if (!mdev_devnod || *mdev_devnod == 0) {
-		snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev,
-			 mdev_ch);
-		mdev_devnod = devnod_buf;
-	}
-
-	c = get_channel_by_name(mdev, mdev_ch);
-	if (IS_ERR(c))
-		return -ENODEV;
-
-	if (!c->aim0.ptr)
-		aim_ptr = &c->aim0.ptr;
-	else if (!c->aim1.ptr)
-		aim_ptr = &c->aim1.ptr;
-	else
-		return -ENOSPC;
-
-	*aim_ptr = aim_obj->driver;
-	ret = aim_obj->driver->probe_channel(c->iface, c->channel_id,
-					     &c->cfg, &c->kobj, mdev_devnod);
-	if (ret) {
-		*aim_ptr = NULL;
-		return ret;
-	}
-
-	return len;
-}
-
-/**
- * remove_link_store - store function for remove_link attribute
- * @aim_obj: pointer to AIM object
- * @attr: its attributes
- * @buf: buffer
- * @len: buffer length
- *
- * Example:
- * echo "mdev0:ep81" >remove_link
- */
-static ssize_t remove_link_store(struct most_aim_obj *aim_obj,
-				 struct most_aim_attribute *attr,
-				 const char *buf,
-				 size_t len)
-{
-	struct most_c_obj *c;
-	char buffer[STRING_SIZE];
-	char *mdev;
-	char *mdev_ch;
-	int ret;
-	size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
-
-	strlcpy(buffer, buf, max_len);
-	ret = split_string(buffer, &mdev, &mdev_ch, NULL);
-	if (ret)
-		return ret;
-
-	c = get_channel_by_name(mdev, mdev_ch);
-	if (IS_ERR(c))
-		return -ENODEV;
-
-	if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id))
-		return -EIO;
-	if (c->aim0.ptr == aim_obj->driver)
-		c->aim0.ptr = NULL;
-	if (c->aim1.ptr == aim_obj->driver)
-		c->aim1.ptr = NULL;
-	return len;
-}
-
-static struct most_aim_attribute most_aim_attrs[] = {
-	__ATTR_RO(links),
-	__ATTR_WO(add_link),
-	__ATTR_WO(remove_link),
-};
-
-static struct attribute *most_aim_def_attrs[] = {
-	&most_aim_attrs[0].attr,
-	&most_aim_attrs[1].attr,
-	&most_aim_attrs[2].attr,
-	NULL,
-};
-
-static struct kobj_type most_aim_ktype = {
-	.sysfs_ops = &most_aim_sysfs_ops,
-	.release = most_aim_release,
-	.default_attrs = most_aim_def_attrs,
-};
-
-static struct kset *most_aim_kset;
-
-/**
- * create_most_aim_obj - creates an AIM object
- * @name: name of the AIM
- *
- * This creates an AIM object assigns the proper kset and registers
- * it with sysfs.
- * Returns a pointer to the object or NULL if something went wrong.
- */
-static struct most_aim_obj *create_most_aim_obj(const char *name)
-{
-	struct most_aim_obj *most_aim;
-	int retval;
-
-	most_aim = kzalloc(sizeof(*most_aim), GFP_KERNEL);
-	if (!most_aim)
-		return NULL;
-	most_aim->kobj.kset = most_aim_kset;
-	retval = kobject_init_and_add(&most_aim->kobj, &most_aim_ktype,
-				      NULL, "%s", name);
-	if (retval) {
-		kobject_put(&most_aim->kobj);
-		return NULL;
-	}
-	kobject_uevent(&most_aim->kobj, KOBJ_ADD);
-	return most_aim;
-}
-
-/**
- * destroy_most_aim_obj - AIM release function
- * @p: pointer to AIM object
- *
- * This decrements the reference counter of the AIM object. If the
- * reference count turns zero, its release function will be called.
- */
-static void destroy_most_aim_obj(struct most_aim_obj *p)
-{
-	kobject_put(&p->kobj);
-}
-
-/*		     ___       ___
- *		     ___C O R E___
- */
-
-/**
- * Instantiation of the MOST bus
- */
-static struct bus_type most_bus = {
-	.name = "most",
-};
-
-/**
- * Instantiation of the core driver
- */
-static struct device_driver mostcore = {
-	.name = "mostcore",
-	.bus = &most_bus,
-};
-
-static inline void trash_mbo(struct mbo *mbo)
-{
-	unsigned long flags;
-	struct most_c_obj *c = mbo->context;
-
-	spin_lock_irqsave(&c->fifo_lock, flags);
-	list_add(&mbo->list, &c->trash_fifo);
-	spin_unlock_irqrestore(&c->fifo_lock, flags);
-}
-
-static bool hdm_mbo_ready(struct most_c_obj *c)
-{
-	bool empty;
-
-	if (c->enqueue_halt)
-		return false;
-
-	spin_lock_irq(&c->fifo_lock);
-	empty = list_empty(&c->halt_fifo);
-	spin_unlock_irq(&c->fifo_lock);
-
-	return !empty;
-}
-
-static void nq_hdm_mbo(struct mbo *mbo)
-{
-	unsigned long flags;
-	struct most_c_obj *c = mbo->context;
-
-	spin_lock_irqsave(&c->fifo_lock, flags);
-	list_add_tail(&mbo->list, &c->halt_fifo);
-	spin_unlock_irqrestore(&c->fifo_lock, flags);
-	wake_up_interruptible(&c->hdm_fifo_wq);
-}
-
-static int hdm_enqueue_thread(void *data)
-{
-	struct most_c_obj *c = data;
-	struct mbo *mbo;
-	int ret;
-	typeof(c->iface->enqueue) enqueue = c->iface->enqueue;
-
-	while (likely(!kthread_should_stop())) {
-		wait_event_interruptible(c->hdm_fifo_wq,
-					 hdm_mbo_ready(c) ||
-					 kthread_should_stop());
-
-		mutex_lock(&c->nq_mutex);
-		spin_lock_irq(&c->fifo_lock);
-		if (unlikely(c->enqueue_halt || list_empty(&c->halt_fifo))) {
-			spin_unlock_irq(&c->fifo_lock);
-			mutex_unlock(&c->nq_mutex);
-			continue;
-		}
-
-		mbo = list_pop_mbo(&c->halt_fifo);
-		spin_unlock_irq(&c->fifo_lock);
-
-		if (c->cfg.direction == MOST_CH_RX)
-			mbo->buffer_length = c->cfg.buffer_size;
-
-		ret = enqueue(mbo->ifp, mbo->hdm_channel_id, mbo);
-		mutex_unlock(&c->nq_mutex);
-
-		if (unlikely(ret)) {
-			pr_err("hdm enqueue failed\n");
-			nq_hdm_mbo(mbo);
-			c->hdm_enqueue_task = NULL;
-			return 0;
-		}
-	}
-
-	return 0;
-}
-
-static int run_enqueue_thread(struct most_c_obj *c, int channel_id)
-{
-	struct task_struct *task =
-		kthread_run(hdm_enqueue_thread, c, "hdm_fifo_%d",
-			    channel_id);
-
-	if (IS_ERR(task))
-		return PTR_ERR(task);
-
-	c->hdm_enqueue_task = task;
-	return 0;
-}
-
-/**
- * arm_mbo - recycle MBO for further usage
- * @mbo: buffer object
- *
- * This puts an MBO back to the list to have it ready for up coming
- * tx transactions.
- *
- * In case the MBO belongs to a channel that recently has been
- * poisoned, the MBO is scheduled to be trashed.
- * Calls the completion handler of an attached AIM.
- */
-static void arm_mbo(struct mbo *mbo)
-{
-	unsigned long flags;
-	struct most_c_obj *c;
-
-	BUG_ON((!mbo) || (!mbo->context));
-	c = mbo->context;
-
-	if (c->is_poisoned) {
-		trash_mbo(mbo);
-		return;
-	}
-
-	spin_lock_irqsave(&c->fifo_lock, flags);
-	++*mbo->num_buffers_ptr;
-	list_add_tail(&mbo->list, &c->fifo);
-	spin_unlock_irqrestore(&c->fifo_lock, flags);
-
-	if (c->aim0.refs && c->aim0.ptr->tx_completion)
-		c->aim0.ptr->tx_completion(c->iface, c->channel_id);
-
-	if (c->aim1.refs && c->aim1.ptr->tx_completion)
-		c->aim1.ptr->tx_completion(c->iface, c->channel_id);
-}
-
-/**
- * arm_mbo_chain - helper function that arms an MBO chain for the HDM
- * @c: pointer to interface channel
- * @dir: direction of the channel
- * @compl: pointer to completion function
- *
- * This allocates buffer objects including the containing DMA coherent
- * buffer and puts them in the fifo.
- * Buffers of Rx channels are put in the kthread fifo, hence immediately
- * submitted to the HDM.
- *
- * Returns the number of allocated and enqueued MBOs.
- */
-static int arm_mbo_chain(struct most_c_obj *c, int dir,
-			 void (*compl)(struct mbo *))
-{
-	unsigned int i;
-	int retval;
-	struct mbo *mbo;
-	u32 coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
-
-	atomic_set(&c->mbo_nq_level, 0);
-
-	for (i = 0; i < c->cfg.num_buffers; i++) {
-		mbo = kzalloc(sizeof(*mbo), GFP_KERNEL);
-		if (!mbo) {
-			retval = i;
-			goto _exit;
-		}
-		mbo->context = c;
-		mbo->ifp = c->iface;
-		mbo->hdm_channel_id = c->channel_id;
-		mbo->virt_address = dma_alloc_coherent(NULL,
-						       coherent_buf_size,
-						       &mbo->bus_address,
-						       GFP_KERNEL);
-		if (!mbo->virt_address) {
-			pr_info("WARN: No DMA coherent buffer.\n");
-			retval = i;
-			goto _error1;
-		}
-		mbo->complete = compl;
-		mbo->num_buffers_ptr = &dummy_num_buffers;
-		if (dir == MOST_CH_RX) {
-			nq_hdm_mbo(mbo);
-			atomic_inc(&c->mbo_nq_level);
-		} else {
-			arm_mbo(mbo);
-		}
-	}
-	return i;
-
-_error1:
-	kfree(mbo);
-_exit:
-	return retval;
-}
-
-/**
- * most_submit_mbo - submits an MBO to fifo
- * @mbo: pointer to the MBO
- */
-void most_submit_mbo(struct mbo *mbo)
-{
-	if (WARN_ONCE(!mbo || !mbo->context,
-		      "bad mbo or missing channel reference\n"))
-		return;
-
-	nq_hdm_mbo(mbo);
-}
-EXPORT_SYMBOL_GPL(most_submit_mbo);
-
-/**
- * most_write_completion - write completion handler
- * @mbo: pointer to MBO
- *
- * This recycles the MBO for further usage. In case the channel has been
- * poisoned, the MBO is scheduled to be trashed.
- */
-static void most_write_completion(struct mbo *mbo)
-{
-	struct most_c_obj *c;
-
-	BUG_ON((!mbo) || (!mbo->context));
-
-	c = mbo->context;
-	if (mbo->status == MBO_E_INVAL)
-		pr_info("WARN: Tx MBO status: invalid\n");
-	if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE)))
-		trash_mbo(mbo);
-	else
-		arm_mbo(mbo);
-}
-
-/**
- * get_channel_by_iface - get pointer to channel object
- * @iface: pointer to interface instance
- * @id: channel ID
- *
- * This retrieves a pointer to a channel of the given interface and channel ID.
- */
-static struct
-most_c_obj *get_channel_by_iface(struct most_interface *iface, int id)
-{
-	struct most_inst_obj *i;
-
-	if (unlikely(!iface)) {
-		pr_err("Bad interface\n");
-		return NULL;
-	}
-	if (unlikely((id < 0) || (id >= iface->num_channels))) {
-		pr_err("Channel index (%d) out of range\n", id);
-		return NULL;
-	}
-	i = iface->priv;
-	if (unlikely(!i)) {
-		pr_err("interface is not registered\n");
-		return NULL;
-	}
-	return i->channel[id];
-}
-
-int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim)
-{
-	struct most_c_obj *c = get_channel_by_iface(iface, id);
-	unsigned long flags;
-	int empty;
-
-	if (unlikely(!c))
-		return -EINVAL;
-
-	if (c->aim0.refs && c->aim1.refs &&
-	    ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) ||
-	     (aim == c->aim1.ptr && c->aim1.num_buffers <= 0)))
-		return 0;
-
-	spin_lock_irqsave(&c->fifo_lock, flags);
-	empty = list_empty(&c->fifo);
-	spin_unlock_irqrestore(&c->fifo_lock, flags);
-	return !empty;
-}
-EXPORT_SYMBOL_GPL(channel_has_mbo);
-
-/**
- * most_get_mbo - get pointer to an MBO of pool
- * @iface: pointer to interface instance
- * @id: channel ID
- *
- * This attempts to get a free buffer out of the channel fifo.
- * Returns a pointer to MBO on success or NULL otherwise.
- */
-struct mbo *most_get_mbo(struct most_interface *iface, int id,
-			 struct most_aim *aim)
-{
-	struct mbo *mbo;
-	struct most_c_obj *c;
-	unsigned long flags;
-	int *num_buffers_ptr;
-
-	c = get_channel_by_iface(iface, id);
-	if (unlikely(!c))
-		return NULL;
-
-	if (c->aim0.refs && c->aim1.refs &&
-	    ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) ||
-	     (aim == c->aim1.ptr && c->aim1.num_buffers <= 0)))
-		return NULL;
-
-	if (aim == c->aim0.ptr)
-		num_buffers_ptr = &c->aim0.num_buffers;
-	else if (aim == c->aim1.ptr)
-		num_buffers_ptr = &c->aim1.num_buffers;
-	else
-		num_buffers_ptr = &dummy_num_buffers;
-
-	spin_lock_irqsave(&c->fifo_lock, flags);
-	if (list_empty(&c->fifo)) {
-		spin_unlock_irqrestore(&c->fifo_lock, flags);
-		return NULL;
-	}
-	mbo = list_pop_mbo(&c->fifo);
-	--*num_buffers_ptr;
-	spin_unlock_irqrestore(&c->fifo_lock, flags);
-
-	mbo->num_buffers_ptr = num_buffers_ptr;
-	mbo->buffer_length = c->cfg.buffer_size;
-	return mbo;
-}
-EXPORT_SYMBOL_GPL(most_get_mbo);
-
-/**
- * most_put_mbo - return buffer to pool
- * @mbo: buffer object
- */
-void most_put_mbo(struct mbo *mbo)
-{
-	struct most_c_obj *c = mbo->context;
-
-	if (c->cfg.direction == MOST_CH_TX) {
-		arm_mbo(mbo);
-		return;
-	}
-	nq_hdm_mbo(mbo);
-	atomic_inc(&c->mbo_nq_level);
-}
-EXPORT_SYMBOL_GPL(most_put_mbo);
-
-/**
- * most_read_completion - read completion handler
- * @mbo: pointer to MBO
- *
- * This function is called by the HDM when data has been received from the
- * hardware and copied to the buffer of the MBO.
- *
- * In case the channel has been poisoned it puts the buffer in the trash queue.
- * Otherwise, it passes the buffer to an AIM for further processing.
- */
-static void most_read_completion(struct mbo *mbo)
-{
-	struct most_c_obj *c = mbo->context;
-
-	if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) {
-		trash_mbo(mbo);
-		return;
-	}
-
-	if (mbo->status == MBO_E_INVAL) {
-		nq_hdm_mbo(mbo);
-		atomic_inc(&c->mbo_nq_level);
-		return;
-	}
-
-	if (atomic_sub_and_test(1, &c->mbo_nq_level))
-		c->is_starving = 1;
-
-	if (c->aim0.refs && c->aim0.ptr->rx_completion &&
-	    c->aim0.ptr->rx_completion(mbo) == 0)
-		return;
-
-	if (c->aim1.refs && c->aim1.ptr->rx_completion &&
-	    c->aim1.ptr->rx_completion(mbo) == 0)
-		return;
-
-	most_put_mbo(mbo);
-}
-
-/**
- * most_start_channel - prepares a channel for communication
- * @iface: pointer to interface instance
- * @id: channel ID
- *
- * This prepares the channel for usage. Cross-checks whether the
- * channel's been properly configured.
- *
- * Returns 0 on success or error code otherwise.
- */
-int most_start_channel(struct most_interface *iface, int id,
-		       struct most_aim *aim)
-{
-	int num_buffer;
-	int ret;
-	struct most_c_obj *c = get_channel_by_iface(iface, id);
-
-	if (unlikely(!c))
-		return -EINVAL;
-
-	mutex_lock(&c->start_mutex);
-	if (c->aim0.refs + c->aim1.refs > 0)
-		goto out; /* already started by other aim */
-
-	if (!try_module_get(iface->mod)) {
-		pr_info("failed to acquire HDM lock\n");
-		mutex_unlock(&c->start_mutex);
-		return -ENOLCK;
-	}
-
-	c->cfg.extra_len = 0;
-	if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) {
-		pr_info("channel configuration failed. Go check settings...\n");
-		ret = -EINVAL;
-		goto error;
-	}
-
-	init_waitqueue_head(&c->hdm_fifo_wq);
-
-	if (c->cfg.direction == MOST_CH_RX)
-		num_buffer = arm_mbo_chain(c, c->cfg.direction,
-					   most_read_completion);
-	else
-		num_buffer = arm_mbo_chain(c, c->cfg.direction,
-					   most_write_completion);
-	if (unlikely(!num_buffer)) {
-		pr_info("failed to allocate memory\n");
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	ret = run_enqueue_thread(c, id);
-	if (ret)
-		goto error;
-
-	c->is_starving = 0;
-	c->aim0.num_buffers = c->cfg.num_buffers / 2;
-	c->aim1.num_buffers = c->cfg.num_buffers - c->aim0.num_buffers;
-	atomic_set(&c->mbo_ref, num_buffer);
-
-out:
-	if (aim == c->aim0.ptr)
-		c->aim0.refs++;
-	if (aim == c->aim1.ptr)
-		c->aim1.refs++;
-	mutex_unlock(&c->start_mutex);
-	return 0;
-
-error:
-	module_put(iface->mod);
-	mutex_unlock(&c->start_mutex);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(most_start_channel);
-
-/**
- * most_stop_channel - stops a running channel
- * @iface: pointer to interface instance
- * @id: channel ID
- */
-int most_stop_channel(struct most_interface *iface, int id,
-		      struct most_aim *aim)
-{
-	struct most_c_obj *c;
-
-	if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) {
-		pr_err("Bad interface or index out of range\n");
-		return -EINVAL;
-	}
-	c = get_channel_by_iface(iface, id);
-	if (unlikely(!c))
-		return -EINVAL;
-
-	mutex_lock(&c->start_mutex);
-	if (c->aim0.refs + c->aim1.refs >= 2)
-		goto out;
-
-	if (c->hdm_enqueue_task)
-		kthread_stop(c->hdm_enqueue_task);
-	c->hdm_enqueue_task = NULL;
-
-	if (iface->mod)
-		module_put(iface->mod);
-
-	c->is_poisoned = true;
-	if (c->iface->poison_channel(c->iface, c->channel_id)) {
-		pr_err("Cannot stop channel %d of mdev %s\n", c->channel_id,
-		       c->iface->description);
-		mutex_unlock(&c->start_mutex);
-		return -EAGAIN;
-	}
-	flush_trash_fifo(c);
-	flush_channel_fifos(c);
-
-#ifdef CMPL_INTERRUPTIBLE
-	if (wait_for_completion_interruptible(&c->cleanup)) {
-		pr_info("Interrupted while clean up ch %d\n", c->channel_id);
-		mutex_unlock(&c->start_mutex);
-		return -EINTR;
-	}
-#else
-	wait_for_completion(&c->cleanup);
-#endif
-	c->is_poisoned = false;
-
-out:
-	if (aim == c->aim0.ptr)
-		c->aim0.refs--;
-	if (aim == c->aim1.ptr)
-		c->aim1.refs--;
-	mutex_unlock(&c->start_mutex);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(most_stop_channel);
-
-/**
- * most_register_aim - registers an AIM (driver) with the core
- * @aim: instance of AIM to be registered
- */
-int most_register_aim(struct most_aim *aim)
-{
-	struct most_aim_obj *aim_obj;
-
-	if (!aim) {
-		pr_err("Bad driver\n");
-		return -EINVAL;
-	}
-	aim_obj = create_most_aim_obj(aim->name);
-	if (!aim_obj) {
-		pr_info("failed to alloc driver object\n");
-		return -ENOMEM;
-	}
-	aim_obj->driver = aim;
-	aim->context = aim_obj;
-	pr_info("registered new application interfacing module %s\n",
-		aim->name);
-	list_add_tail(&aim_obj->list, &aim_list);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(most_register_aim);
-
-/**
- * most_deregister_aim - deregisters an AIM (driver) with the core
- * @aim: AIM to be removed
- */
-int most_deregister_aim(struct most_aim *aim)
-{
-	struct most_aim_obj *aim_obj;
-	struct most_c_obj *c, *tmp;
-	struct most_inst_obj *i, *i_tmp;
-
-	if (!aim) {
-		pr_err("Bad driver\n");
-		return -EINVAL;
-	}
-
-	aim_obj = aim->context;
-	if (!aim_obj) {
-		pr_info("driver not registered.\n");
-		return -EINVAL;
-	}
-	list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
-		list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
-			if (c->aim0.ptr == aim || c->aim1.ptr == aim)
-				aim->disconnect_channel(
-					c->iface, c->channel_id);
-			if (c->aim0.ptr == aim)
-				c->aim0.ptr = NULL;
-			if (c->aim1.ptr == aim)
-				c->aim1.ptr = NULL;
-		}
-	}
-	list_del(&aim_obj->list);
-	destroy_most_aim_obj(aim_obj);
-	pr_info("deregistering application interfacing module %s\n", aim->name);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(most_deregister_aim);
-
-/**
- * most_register_interface - registers an interface with core
- * @iface: pointer to the instance of the interface description.
- *
- * Allocates and initializes a new interface instance and all of its channels.
- * Returns a pointer to kobject or an error pointer.
- */
-struct kobject *most_register_interface(struct most_interface *iface)
-{
-	unsigned int i;
-	int id;
-	char name[STRING_SIZE];
-	char channel_name[STRING_SIZE];
-	struct most_c_obj *c;
-	struct most_inst_obj *inst;
-
-	if (!iface || !iface->enqueue || !iface->configure ||
-	    !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) {
-		pr_err("Bad interface or channel overflow\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL);
-	if (id < 0) {
-		pr_info("Failed to alloc mdev ID\n");
-		return ERR_PTR(id);
-	}
-	snprintf(name, STRING_SIZE, "mdev%d", id);
-
-	inst = create_most_inst_obj(name);
-	if (!inst) {
-		pr_info("Failed to allocate interface instance\n");
-		ida_simple_remove(&mdev_id, id);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	iface->priv = inst;
-	INIT_LIST_HEAD(&inst->channel_list);
-	inst->iface = iface;
-	inst->dev_id = id;
-	list_add_tail(&inst->list, &instance_list);
-
-	for (i = 0; i < iface->num_channels; i++) {
-		const char *name_suffix = iface->channel_vector[i].name_suffix;
-
-		if (!name_suffix)
-			snprintf(channel_name, STRING_SIZE, "ch%d", i);
-		else
-			snprintf(channel_name, STRING_SIZE, "%s", name_suffix);
-
-		/* this increments the reference count of this instance */
-		c = create_most_c_obj(channel_name, &inst->kobj);
-		if (!c)
-			goto free_instance;
-		inst->channel[i] = c;
-		c->is_starving = 0;
-		c->iface = iface;
-		c->inst = inst;
-		c->channel_id = i;
-		c->keep_mbo = false;
-		c->enqueue_halt = false;
-		c->is_poisoned = false;
-		c->cfg.direction = 0;
-		c->cfg.data_type = 0;
-		c->cfg.num_buffers = 0;
-		c->cfg.buffer_size = 0;
-		c->cfg.subbuffer_size = 0;
-		c->cfg.packets_per_xact = 0;
-		spin_lock_init(&c->fifo_lock);
-		INIT_LIST_HEAD(&c->fifo);
-		INIT_LIST_HEAD(&c->trash_fifo);
-		INIT_LIST_HEAD(&c->halt_fifo);
-		init_completion(&c->cleanup);
-		atomic_set(&c->mbo_ref, 0);
-		mutex_init(&c->start_mutex);
-		mutex_init(&c->nq_mutex);
-		list_add_tail(&c->list, &inst->channel_list);
-	}
-	pr_info("registered new MOST device mdev%d (%s)\n",
-		inst->dev_id, iface->description);
-	return &inst->kobj;
-
-free_instance:
-	pr_info("Failed allocate channel(s)\n");
-	list_del(&inst->list);
-	ida_simple_remove(&mdev_id, id);
-	destroy_most_inst_obj(inst);
-	return ERR_PTR(-ENOMEM);
-}
-EXPORT_SYMBOL_GPL(most_register_interface);
-
-/**
- * most_deregister_interface - deregisters an interface with core
- * @iface: pointer to the interface instance description.
- *
- * Before removing an interface instance from the list, all running
- * channels are stopped and poisoned.
- */
-void most_deregister_interface(struct most_interface *iface)
-{
-	struct most_inst_obj *i = iface->priv;
-	struct most_c_obj *c;
-
-	if (unlikely(!i)) {
-		pr_info("Bad Interface\n");
-		return;
-	}
-	pr_info("deregistering MOST device %s (%s)\n", i->kobj.name,
-		iface->description);
-
-	list_for_each_entry(c, &i->channel_list, list) {
-		if (c->aim0.ptr)
-			c->aim0.ptr->disconnect_channel(c->iface,
-							c->channel_id);
-		if (c->aim1.ptr)
-			c->aim1.ptr->disconnect_channel(c->iface,
-							c->channel_id);
-		c->aim0.ptr = NULL;
-		c->aim1.ptr = NULL;
-	}
-
-	ida_simple_remove(&mdev_id, i->dev_id);
-	list_del(&i->list);
-	destroy_most_inst_obj(i);
-}
-EXPORT_SYMBOL_GPL(most_deregister_interface);
-
-/**
- * most_stop_enqueue - prevents core from enqueueing MBOs
- * @iface: pointer to interface
- * @id: channel id
- *
- * This is called by an HDM that _cannot_ attend to its duties and
- * is imminent to get run over by the core. The core is not going to
- * enqueue any further packets unless the flagging HDM calls
- * most_resume enqueue().
- */
-void most_stop_enqueue(struct most_interface *iface, int id)
-{
-	struct most_c_obj *c = get_channel_by_iface(iface, id);
-
-	if (!c)
-		return;
-
-	mutex_lock(&c->nq_mutex);
-	c->enqueue_halt = true;
-	mutex_unlock(&c->nq_mutex);
-}
-EXPORT_SYMBOL_GPL(most_stop_enqueue);
-
-/**
- * most_resume_enqueue - allow core to enqueue MBOs again
- * @iface: pointer to interface
- * @id: channel id
- *
- * This clears the enqueue halt flag and enqueues all MBOs currently
- * sitting in the wait fifo.
- */
-void most_resume_enqueue(struct most_interface *iface, int id)
-{
-	struct most_c_obj *c = get_channel_by_iface(iface, id);
-
-	if (!c)
-		return;
-
-	mutex_lock(&c->nq_mutex);
-	c->enqueue_halt = false;
-	mutex_unlock(&c->nq_mutex);
-
-	wake_up_interruptible(&c->hdm_fifo_wq);
-}
-EXPORT_SYMBOL_GPL(most_resume_enqueue);
-
-static int __init most_init(void)
-{
-	int err;
-
-	pr_info("init()\n");
-	INIT_LIST_HEAD(&instance_list);
-	INIT_LIST_HEAD(&aim_list);
-	ida_init(&mdev_id);
-
-	err = bus_register(&most_bus);
-	if (err) {
-		pr_info("Cannot register most bus\n");
-		return err;
-	}
-
-	most_class = class_create(THIS_MODULE, "most");
-	if (IS_ERR(most_class)) {
-		pr_info("No udev support.\n");
-		err = PTR_ERR(most_class);
-		goto exit_bus;
-	}
-
-	err = driver_register(&mostcore);
-	if (err) {
-		pr_info("Cannot register core driver\n");
-		goto exit_class;
-	}
-
-	core_dev = device_create(most_class, NULL, 0, NULL, "mostcore");
-	if (IS_ERR(core_dev)) {
-		err = PTR_ERR(core_dev);
-		goto exit_driver;
-	}
-
-	most_aim_kset = kset_create_and_add("aims", NULL, &core_dev->kobj);
-	if (!most_aim_kset) {
-		err = -ENOMEM;
-		goto exit_class_container;
-	}
-
-	most_inst_kset = kset_create_and_add("devices", NULL, &core_dev->kobj);
-	if (!most_inst_kset) {
-		err = -ENOMEM;
-		goto exit_driver_kset;
-	}
-
-	return 0;
-
-exit_driver_kset:
-	kset_unregister(most_aim_kset);
-exit_class_container:
-	device_destroy(most_class, 0);
-exit_driver:
-	driver_unregister(&mostcore);
-exit_class:
-	class_destroy(most_class);
-exit_bus:
-	bus_unregister(&most_bus);
-	return err;
-}
-
-static void __exit most_exit(void)
-{
-	struct most_inst_obj *i, *i_tmp;
-	struct most_aim_obj *d, *d_tmp;
-
-	pr_info("exit core module\n");
-	list_for_each_entry_safe(d, d_tmp, &aim_list, list) {
-		destroy_most_aim_obj(d);
-	}
-
-	list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
-		list_del(&i->list);
-		destroy_most_inst_obj(i);
-	}
-	kset_unregister(most_inst_kset);
-	kset_unregister(most_aim_kset);
-	device_destroy(most_class, 0);
-	driver_unregister(&mostcore);
-	class_destroy(most_class);
-	bus_unregister(&most_bus);
-	ida_destroy(&mdev_id);
-}
-
-module_init(most_init);
-module_exit(most_exit);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
-MODULE_DESCRIPTION("Core module of stacked MOST Linux driver");
diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h
deleted file mode 100644
index 915e515..0000000
--- a/drivers/staging/most/mostcore/mostcore.h
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * mostcore.h - Interface between MostCore,
- *   Hardware Dependent Module (HDM) and Application Interface Module (AIM).
- *
- * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * 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.
- *
- * This file is licensed under GPLv2.
- */
-
-/*
- * Authors:
- *   Andrey Shvetsov <andrey.shvetsov@k2l.de>
- *   Christian Gromm <christian.gromm@microchip.com>
- *   Sebastian Graf
- */
-
-#ifndef __MOST_CORE_H__
-#define __MOST_CORE_H__
-
-#include <linux/types.h>
-
-struct kobject;
-struct module;
-
-/**
- * Interface type
- */
-enum most_interface_type {
-	ITYPE_LOOPBACK = 1,
-	ITYPE_I2C,
-	ITYPE_I2S,
-	ITYPE_TSI,
-	ITYPE_HBI,
-	ITYPE_MEDIALB_DIM,
-	ITYPE_MEDIALB_DIM2,
-	ITYPE_USB,
-	ITYPE_PCIE
-};
-
-/**
- * Channel direction.
- */
-enum most_channel_direction {
-	MOST_CH_RX = 1 << 0,
-	MOST_CH_TX = 1 << 1,
-};
-
-/**
- * Channel data type.
- */
-enum most_channel_data_type {
-	MOST_CH_CONTROL = 1 << 0,
-	MOST_CH_ASYNC = 1 << 1,
-	MOST_CH_ISOC = 1 << 2,
-	MOST_CH_SYNC = 1 << 5,
-};
-
-enum mbo_status_flags {
-	/* MBO was processed successfully (data was send or received )*/
-	MBO_SUCCESS = 0,
-	/* The MBO contains wrong or missing information.  */
-	MBO_E_INVAL,
-	/* MBO was completed as HDM Channel will be closed */
-	MBO_E_CLOSE,
-};
-
-/**
- * struct most_channel_capability - Channel capability
- * @direction: Supported channel directions.
- * The value is bitwise OR-combination of the values from the
- * enumeration most_channel_direction. Zero is allowed value and means
- * "channel may not be used".
- * @data_type: Supported channel data types.
- * The value is bitwise OR-combination of the values from the
- * enumeration most_channel_data_type. Zero is allowed value and means
- * "channel may not be used".
- * @num_buffer_packet: Maximum number of buffers supported by this channel
- * for packet data types (Async,Control,QoS)
- * @buffer_size_packet: Maximum buffer size supported by this channel
- * for packet data types (Async,Control,QoS)
- * @num_buffer_streaming: Maximum number of buffers supported by this channel
- * for streaming data types (Sync,AV Packetized)
- * @buffer_size_streaming: Maximum buffer size supported by this channel
- * for streaming data types (Sync,AV Packetized)
- * @name_suffix: Optional suffix providean by an HDM that is attached to the
- * regular channel name.
- *
- * Describes the capabilities of a MostCore channel like supported Data Types
- * and directions. This information is provided by an HDM for the MostCore.
- *
- * The Core creates read only sysfs attribute files in
- * /sys/devices/virtual/most/mostcore/devices/mdev-#/mdev#-ch#/ with the
- * following attributes:
- *	-available_directions
- *	-available_datatypes
- *	-number_of_packet_buffers
- *	-number_of_stream_buffers
- *	-size_of_packet_buffer
- *	-size_of_stream_buffer
- * where content of each file is a string with all supported properties of this
- * very channel attribute.
- */
-struct most_channel_capability {
-	u16 direction;
-	u16 data_type;
-	u16 num_buffers_packet;
-	u16 buffer_size_packet;
-	u16 num_buffers_streaming;
-	u16 buffer_size_streaming;
-	const char *name_suffix;
-};
-
-/**
- * struct most_channel_config - stores channel configuration
- * @direction: direction of the channel
- * @data_type: data type travelling over this channel
- * @num_buffers: number of buffers
- * @buffer_size: size of a buffer for AIM.
- * Buffer size may be cutted down by HDM in a configure callback
- * to match to a given interface and channel type.
- * @extra_len: additional buffer space for internal HDM purposes like padding.
- * May be set by HDM in a configure callback if needed.
- * @subbuffer_size: size of a subbuffer
- * @packets_per_xact: number of MOST frames that are packet inside one USB
- *		      packet. This is USB specific
- *
- * Describes the configuration for a MostCore channel. This information is
- * provided from the MostCore to a HDM (like the Medusa PCIe Interface) as a
- * parameter of the "configure" function call.
- */
-struct most_channel_config {
-	enum most_channel_direction direction;
-	enum most_channel_data_type data_type;
-	u16 num_buffers;
-	u16 buffer_size;
-	u16 extra_len;
-	u16 subbuffer_size;
-	u16 packets_per_xact;
-};
-
-/*
- * struct mbo - MOST Buffer Object.
- * @context: context for core completion handler
- * @priv: private data for HDM
- *
- *	public: documented fields that are used for the communications
- *	between MostCore and HDMs
- *
- * @list: list head for use by the mbo's current owner
- * @ifp: (in) associated interface instance
- * @hdm_channel_id: (in) HDM channel instance
- * @virt_address: (in) kernel virtual address of the buffer
- * @bus_address: (in) bus address of the buffer
- * @buffer_length: (in) buffer payload length
- * @processed_length: (out) processed length
- * @status: (out) transfer status
- * @complete: (in) completion routine
- *
- * The MostCore allocates and initializes the MBO.
- *
- * The HDM receives MBO for transfer from MostCore with the call to enqueue().
- * The HDM copies the data to- or from the buffer depending on configured
- * channel direction, set "processed_length" and "status" and completes
- * the transfer procedure by calling the completion routine.
- *
- * At the end the MostCore deallocates the MBO or recycles it for further
- * transfers for the same or different HDM.
- *
- * Directions of usage:
- * The core driver should never access any MBO fields (even if marked
- * as "public") while the MBO is owned by an HDM. The ownership starts with
- * the call of enqueue() and ends with the call of its complete() routine.
- *
- *					II.
- * Every HDM attached to the core driver _must_ ensure that it returns any MBO
- * it owns (due to a previous call to enqueue() by the core driver) before it
- * de-registers an interface or gets unloaded from the kernel. If this direction
- * is violated memory leaks will occur, since the core driver does _not_ track
- * MBOs it is currently not in control of.
- *
- */
-struct mbo {
-	void *context;
-	void *priv;
-	struct list_head list;
-	struct most_interface *ifp;
-	int *num_buffers_ptr;
-	u16 hdm_channel_id;
-	void *virt_address;
-	dma_addr_t bus_address;
-	u16 buffer_length;
-	u16 processed_length;
-	enum mbo_status_flags status;
-	void (*complete)(struct mbo *);
-};
-
-/**
- * Interface instance description.
- *
- * Describes one instance of an interface like Medusa PCIe or Vantage USB.
- * This structure is allocated and initialized in the HDM. MostCore may not
- * modify this structure.
- *
- * @interface Interface type. \sa most_interface_type.
- * @description PRELIMINARY.
- *   Unique description of the device instance from point of view of the
- *   interface in free text form (ASCII).
- *   It may be a hexadecimal presentation of the memory address for the MediaLB
- *   IP or USB device ID with USB properties for USB interface, etc.
- * @num_channels Number of channels and size of the channel_vector.
- * @channel_vector Properties of the channels.
- *   Array index represents channel ID by the driver.
- * @configure Callback to change data type for the channel of the
- *   interface instance. May be zero if the instance of the interface is not
- *   configurable. Parameter channel_config describes direction and data
- *   type for the channel, configured by the higher level. The content of
- * @enqueue Delivers MBO to the HDM for processing.
- *   After HDM completes Rx- or Tx- operation the processed MBO shall
- *   be returned back to the MostCore using completion routine.
- *   The reason to get the MBO delivered from the MostCore after the channel
- *   is poisoned is the re-opening of the channel by the application.
- *   In this case the HDM shall hold MBOs and service the channel as usual.
- *   The HDM must be able to hold at least one MBO for each channel.
- *   The callback returns a negative value on error, otherwise 0.
- * @poison_channel Informs HDM about closing the channel. The HDM shall
- *   cancel all transfers and synchronously or asynchronously return
- *   all enqueued for this channel MBOs using the completion routine.
- *   The callback returns a negative value on error, otherwise 0.
- * @request_netinfo: triggers retrieving of network info from the HDM by
- *   means of "Message exchange over MDP/MEP"
- *   The call of the function request_netinfo with the parameter on_netinfo as
- *   NULL prohibits use of the previously obtained function pointer.
- * @priv Private field used by mostcore to store context information.
- */
-struct most_interface {
-	struct module *mod;
-	enum most_interface_type interface;
-	const char *description;
-	int num_channels;
-	struct most_channel_capability *channel_vector;
-	int (*configure)(struct most_interface *iface, int channel_idx,
-			 struct most_channel_config *channel_config);
-	int (*enqueue)(struct most_interface *iface, int channel_idx,
-		       struct mbo *mbo);
-	int (*poison_channel)(struct most_interface *iface, int channel_idx);
-	void (*request_netinfo)(struct most_interface *iface, int channel_idx,
-				void (*on_netinfo)(struct most_interface *iface,
-						   unsigned char link_stat,
-						   unsigned char *mac_addr));
-	void *priv;
-};
-
-/**
- * struct most_aim - identifies MOST device driver to mostcore
- * @name: Driver name
- * @probe_channel: function for core to notify driver about channel connection
- * @disconnect_channel: callback function to disconnect a certain channel
- * @rx_completion: completion handler for received packets
- * @tx_completion: completion handler for transmitted packets
- * @context: context pointer to be used by mostcore
- */
-struct most_aim {
-	const char *name;
-	int (*probe_channel)(struct most_interface *iface, int channel_idx,
-			     struct most_channel_config *cfg,
-			     struct kobject *parent, char *name);
-	int (*disconnect_channel)(struct most_interface *iface,
-				  int channel_idx);
-	int (*rx_completion)(struct mbo *mbo);
-	int (*tx_completion)(struct most_interface *iface, int channel_idx);
-	void *context;
-};
-
-/**
- * most_register_interface - Registers instance of the interface.
- * @iface: Pointer to the interface instance description.
- *
- * Returns a pointer to the kobject of the generated instance.
- *
- * Note: HDM has to ensure that any reference held on the kobj is
- * released before deregistering the interface.
- */
-struct kobject *most_register_interface(struct most_interface *iface);
-
-/**
- * Deregisters instance of the interface.
- * @intf_instance Pointer to the interface instance description.
- */
-void most_deregister_interface(struct most_interface *iface);
-void most_submit_mbo(struct mbo *mbo);
-
-/**
- * most_stop_enqueue - prevents core from enqueing MBOs
- * @iface: pointer to interface
- * @channel_idx: channel index
- */
-void most_stop_enqueue(struct most_interface *iface, int channel_idx);
-
-/**
- * most_resume_enqueue - allow core to enqueue MBOs again
- * @iface: pointer to interface
- * @channel_idx: channel index
- *
- * This clears the enqueue halt flag and enqueues all MBOs currently
- * in wait fifo.
- */
-void most_resume_enqueue(struct most_interface *iface, int channel_idx);
-int most_register_aim(struct most_aim *aim);
-int most_deregister_aim(struct most_aim *aim);
-struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx,
-			 struct most_aim *);
-void most_put_mbo(struct mbo *mbo);
-int channel_has_mbo(struct most_interface *iface, int channel_idx,
-		    struct most_aim *aim);
-int most_start_channel(struct most_interface *iface, int channel_idx,
-		       struct most_aim *);
-int most_stop_channel(struct most_interface *iface, int channel_idx,
-		      struct most_aim *);
-
-#endif /* MOST_CORE_H_ */
diff --git a/drivers/staging/most/net/Kconfig b/drivers/staging/most/net/Kconfig
new file mode 100644
index 0000000..795330b
--- /dev/null
+++ b/drivers/staging/most/net/Kconfig
@@ -0,0 +1,13 @@
+#
+# MOST Networking configuration
+#
+
+config MOST_NET
+	tristate "Net"
+	depends on NET
+
+	---help---
+	  Say Y here if you want to commumicate via a networking device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called most_net.
diff --git a/drivers/staging/most/net/Makefile b/drivers/staging/most/net/Makefile
new file mode 100644
index 0000000..54500aa
--- /dev/null
+++ b/drivers/staging/most/net/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_NET) += most_net.o
+
+most_net-objs := net.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c
new file mode 100644
index 0000000..d43aad3
--- /dev/null
+++ b/drivers/staging/most/net/net.c
@@ -0,0 +1,567 @@
+/*
+ * Networking AIM - Networking Application Interface Module for MostCore
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/kobject.h>
+#include <most/core.h>
+
+#define MEP_HDR_LEN 8
+#define MDP_HDR_LEN 16
+#define MAMAC_DATA_LEN (1024 - MDP_HDR_LEN)
+
+#define PMHL 5
+
+#define PMS_TELID_UNSEGM_MAMAC	0x0A
+#define PMS_FIFONO_MDP		0x01
+#define PMS_FIFONO_MEP		0x04
+#define PMS_MSGTYPE_DATA	0x04
+#define PMS_DEF_PRIO		0
+#define MEP_DEF_RETRY		15
+
+#define PMS_FIFONO_MASK		0x07
+#define PMS_FIFONO_SHIFT	3
+#define PMS_RETRY_SHIFT		4
+#define PMS_TELID_MASK		0x0F
+#define PMS_TELID_SHIFT		4
+
+#define HB(value)		((u8)((u16)(value) >> 8))
+#define LB(value)		((u8)(value))
+
+#define EXTRACT_BIT_SET(bitset_name, value) \
+	(((value) >> bitset_name##_SHIFT) & bitset_name##_MASK)
+
+#define PMS_IS_MEP(buf, len) \
+	((len) > MEP_HDR_LEN && \
+	 EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MEP)
+
+#define PMS_IS_MAMAC(buf, len) \
+	((len) > MDP_HDR_LEN && \
+	 EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MDP && \
+	 EXTRACT_BIT_SET(PMS_TELID, (buf)[14]) == PMS_TELID_UNSEGM_MAMAC)
+
+struct net_dev_channel {
+	bool linked;
+	int ch_id;
+};
+
+struct net_dev_context {
+	struct most_interface *iface;
+	bool is_mamac;
+	struct net_device *dev;
+	struct net_dev_channel rx;
+	struct net_dev_channel tx;
+	struct list_head list;
+};
+
+static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
+static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */
+static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */
+static struct most_aim aim;
+
+static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
+{
+	u8 *buff = mbo->virt_address;
+	const u8 broadcast[] = { 0x03, 0xFF };
+	const u8 *dest_addr = skb->data + 4;
+	const u8 *eth_type = skb->data + 12;
+	unsigned int payload_len = skb->len - ETH_HLEN;
+	unsigned int mdp_len = payload_len + MDP_HDR_LEN;
+
+	if (mbo->buffer_length < mdp_len) {
+		pr_err("drop: too small buffer! (%d for %d)\n",
+		       mbo->buffer_length, mdp_len);
+		return -EINVAL;
+	}
+
+	if (skb->len < ETH_HLEN) {
+		pr_err("drop: too small packet! (%d)\n", skb->len);
+		return -EINVAL;
+	}
+
+	if (dest_addr[0] == 0xFF && dest_addr[1] == 0xFF)
+		dest_addr = broadcast;
+
+	*buff++ = HB(mdp_len - 2);
+	*buff++ = LB(mdp_len - 2);
+
+	*buff++ = PMHL;
+	*buff++ = (PMS_FIFONO_MDP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
+	*buff++ = PMS_DEF_PRIO;
+	*buff++ = dest_addr[0];
+	*buff++ = dest_addr[1];
+	*buff++ = 0x00;
+
+	*buff++ = HB(payload_len + 6);
+	*buff++ = LB(payload_len + 6);
+
+	/* end of FPH here */
+
+	*buff++ = eth_type[0];
+	*buff++ = eth_type[1];
+	*buff++ = 0;
+	*buff++ = 0;
+
+	*buff++ = PMS_TELID_UNSEGM_MAMAC << 4 | HB(payload_len);
+	*buff++ = LB(payload_len);
+
+	memcpy(buff, skb->data + ETH_HLEN, payload_len);
+	mbo->buffer_length = mdp_len;
+	return 0;
+}
+
+static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo)
+{
+	u8 *buff = mbo->virt_address;
+	unsigned int mep_len = skb->len + MEP_HDR_LEN;
+
+	if (mbo->buffer_length < mep_len) {
+		pr_err("drop: too small buffer! (%d for %d)\n",
+		       mbo->buffer_length, mep_len);
+		return -EINVAL;
+	}
+
+	*buff++ = HB(mep_len - 2);
+	*buff++ = LB(mep_len - 2);
+
+	*buff++ = PMHL;
+	*buff++ = (PMS_FIFONO_MEP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
+	*buff++ = (MEP_DEF_RETRY << PMS_RETRY_SHIFT) | PMS_DEF_PRIO;
+	*buff++ = 0;
+	*buff++ = 0;
+	*buff++ = 0;
+
+	memcpy(buff, skb->data, skb->len);
+	mbo->buffer_length = mep_len;
+	return 0;
+}
+
+static int most_nd_set_mac_address(struct net_device *dev, void *p)
+{
+	struct net_dev_context *nd = netdev_priv(dev);
+	int err = eth_mac_addr(dev, p);
+
+	if (err)
+		return err;
+
+	nd->is_mamac =
+		(dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 &&
+		 dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0);
+
+	/*
+	 * Set default MTU for the given packet type.
+	 * It is still possible to change MTU using ip tools afterwards.
+	 */
+	dev->mtu = nd->is_mamac ? MAMAC_DATA_LEN : ETH_DATA_LEN;
+
+	return 0;
+}
+
+static void on_netinfo(struct most_interface *iface,
+		       unsigned char link_stat, unsigned char *mac_addr);
+
+static int most_nd_open(struct net_device *dev)
+{
+	struct net_dev_context *nd = netdev_priv(dev);
+	int ret = 0;
+
+	mutex_lock(&probe_disc_mt);
+
+	if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) {
+		netdev_err(dev, "most_start_channel() failed\n");
+		ret = -EBUSY;
+		goto unlock;
+	}
+
+	if (most_start_channel(nd->iface, nd->tx.ch_id, &aim)) {
+		netdev_err(dev, "most_start_channel() failed\n");
+		most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
+		ret = -EBUSY;
+		goto unlock;
+	}
+
+	netif_carrier_off(dev);
+	if (is_valid_ether_addr(dev->dev_addr))
+		netif_dormant_off(dev);
+	else
+		netif_dormant_on(dev);
+	netif_wake_queue(dev);
+	if (nd->iface->request_netinfo)
+		nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, on_netinfo);
+
+unlock:
+	mutex_unlock(&probe_disc_mt);
+	return ret;
+}
+
+static int most_nd_stop(struct net_device *dev)
+{
+	struct net_dev_context *nd = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+	if (nd->iface->request_netinfo)
+		nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, NULL);
+	most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
+	most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
+
+	return 0;
+}
+
+static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb,
+				      struct net_device *dev)
+{
+	struct net_dev_context *nd = netdev_priv(dev);
+	struct mbo *mbo;
+	int ret;
+
+	mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim);
+
+	if (!mbo) {
+		netif_stop_queue(dev);
+		dev->stats.tx_fifo_errors++;
+		return NETDEV_TX_BUSY;
+	}
+
+	if (nd->is_mamac)
+		ret = skb_to_mamac(skb, mbo);
+	else
+		ret = skb_to_mep(skb, mbo);
+
+	if (ret) {
+		most_put_mbo(mbo);
+		dev->stats.tx_dropped++;
+		kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	most_submit_mbo(mbo);
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+	kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops most_nd_ops = {
+	.ndo_open = most_nd_open,
+	.ndo_stop = most_nd_stop,
+	.ndo_start_xmit = most_nd_start_xmit,
+	.ndo_set_mac_address = most_nd_set_mac_address,
+};
+
+static void most_nd_setup(struct net_device *dev)
+{
+	ether_setup(dev);
+	dev->netdev_ops = &most_nd_ops;
+}
+
+static struct net_dev_context *get_net_dev(struct most_interface *iface)
+{
+	struct net_dev_context *nd;
+
+	list_for_each_entry(nd, &net_devices, list)
+		if (nd->iface == iface)
+			return nd;
+	return NULL;
+}
+
+static struct net_dev_context *get_net_dev_hold(struct most_interface *iface)
+{
+	struct net_dev_context *nd;
+	unsigned long flags;
+
+	spin_lock_irqsave(&list_lock, flags);
+	nd = get_net_dev(iface);
+	if (nd && nd->rx.linked && nd->tx.linked)
+		dev_hold(nd->dev);
+	else
+		nd = NULL;
+	spin_unlock_irqrestore(&list_lock, flags);
+	return nd;
+}
+
+static int aim_probe_channel(struct most_interface *iface, int channel_idx,
+			     struct most_channel_config *ccfg,
+			     struct kobject *parent, char *name)
+{
+	struct net_dev_context *nd;
+	struct net_dev_channel *ch;
+	struct net_device *dev;
+	unsigned long flags;
+	int ret = 0;
+
+	if (!iface)
+		return -EINVAL;
+
+	if (ccfg->data_type != MOST_CH_ASYNC)
+		return -EINVAL;
+
+	mutex_lock(&probe_disc_mt);
+	nd = get_net_dev(iface);
+	if (!nd) {
+		dev = alloc_netdev(sizeof(struct net_dev_context), "meth%d",
+				   NET_NAME_UNKNOWN, most_nd_setup);
+		if (!dev) {
+			ret = -ENOMEM;
+			goto unlock;
+		}
+
+		nd = netdev_priv(dev);
+		nd->iface = iface;
+		nd->dev = dev;
+
+		spin_lock_irqsave(&list_lock, flags);
+		list_add(&nd->list, &net_devices);
+		spin_unlock_irqrestore(&list_lock, flags);
+
+		ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
+	} else {
+		ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
+		if (ch->linked) {
+			pr_err("direction is allocated\n");
+			ret = -EINVAL;
+			goto unlock;
+		}
+
+		if (register_netdev(nd->dev)) {
+			pr_err("register_netdev() failed\n");
+			ret = -EINVAL;
+			goto unlock;
+		}
+	}
+	ch->ch_id = channel_idx;
+	ch->linked = true;
+
+unlock:
+	mutex_unlock(&probe_disc_mt);
+	return ret;
+}
+
+static int aim_disconnect_channel(struct most_interface *iface,
+				  int channel_idx)
+{
+	struct net_dev_context *nd;
+	struct net_dev_channel *ch;
+	unsigned long flags;
+	int ret = 0;
+
+	mutex_lock(&probe_disc_mt);
+	nd = get_net_dev(iface);
+	if (!nd) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	if (nd->rx.linked && channel_idx == nd->rx.ch_id) {
+		ch = &nd->rx;
+	} else if (nd->tx.linked && channel_idx == nd->tx.ch_id) {
+		ch = &nd->tx;
+	} else {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	if (nd->rx.linked && nd->tx.linked) {
+		spin_lock_irqsave(&list_lock, flags);
+		ch->linked = false;
+		spin_unlock_irqrestore(&list_lock, flags);
+
+		/*
+		 * do not call most_stop_channel() here, because channels are
+		 * going to be closed in ndo_stop() after unregister_netdev()
+		 */
+		unregister_netdev(nd->dev);
+	} else {
+		spin_lock_irqsave(&list_lock, flags);
+		list_del(&nd->list);
+		spin_unlock_irqrestore(&list_lock, flags);
+
+		free_netdev(nd->dev);
+	}
+
+unlock:
+	mutex_unlock(&probe_disc_mt);
+	return ret;
+}
+
+static int aim_resume_tx_channel(struct most_interface *iface,
+				 int channel_idx)
+{
+	struct net_dev_context *nd;
+
+	nd = get_net_dev_hold(iface);
+	if (!nd)
+		return 0;
+
+	if (nd->tx.ch_id != channel_idx)
+		goto put_nd;
+
+	netif_wake_queue(nd->dev);
+
+put_nd:
+	dev_put(nd->dev);
+	return 0;
+}
+
+static int aim_rx_data(struct mbo *mbo)
+{
+	const u32 zero = 0;
+	struct net_dev_context *nd;
+	char *buf = mbo->virt_address;
+	u32 len = mbo->processed_length;
+	struct sk_buff *skb;
+	struct net_device *dev;
+	unsigned int skb_len;
+	int ret = 0;
+
+	nd = get_net_dev_hold(mbo->ifp);
+	if (!nd)
+		return -EIO;
+
+	if (nd->rx.ch_id != mbo->hdm_channel_id) {
+		ret = -EIO;
+		goto put_nd;
+	}
+
+	dev = nd->dev;
+
+	if (nd->is_mamac) {
+		if (!PMS_IS_MAMAC(buf, len)) {
+			ret = -EIO;
+			goto put_nd;
+		}
+
+		skb = dev_alloc_skb(len - MDP_HDR_LEN + 2 * ETH_ALEN + 2);
+	} else {
+		if (!PMS_IS_MEP(buf, len)) {
+			ret = -EIO;
+			goto put_nd;
+		}
+
+		skb = dev_alloc_skb(len - MEP_HDR_LEN);
+	}
+
+	if (!skb) {
+		dev->stats.rx_dropped++;
+		pr_err_once("drop packet: no memory for skb\n");
+		goto out;
+	}
+
+	skb->dev = dev;
+
+	if (nd->is_mamac) {
+		/* dest */
+		ether_addr_copy(skb_put(skb, ETH_ALEN), dev->dev_addr);
+
+		/* src */
+		skb_put_data(skb, &zero, 4);
+		skb_put_data(skb, buf + 5, 2);
+
+		/* eth type */
+		skb_put_data(skb, buf + 10, 2);
+
+		buf += MDP_HDR_LEN;
+		len -= MDP_HDR_LEN;
+	} else {
+		buf += MEP_HDR_LEN;
+		len -= MEP_HDR_LEN;
+	}
+
+	skb_put_data(skb, buf, len);
+	skb->protocol = eth_type_trans(skb, dev);
+	skb_len = skb->len;
+	if (netif_rx(skb) == NET_RX_SUCCESS) {
+		dev->stats.rx_packets++;
+		dev->stats.rx_bytes += skb_len;
+	} else {
+		dev->stats.rx_dropped++;
+	}
+
+out:
+	most_put_mbo(mbo);
+
+put_nd:
+	dev_put(nd->dev);
+	return ret;
+}
+
+static struct most_aim aim = {
+	.name = "networking",
+	.probe_channel = aim_probe_channel,
+	.disconnect_channel = aim_disconnect_channel,
+	.tx_completion = aim_resume_tx_channel,
+	.rx_completion = aim_rx_data,
+};
+
+static int __init most_net_init(void)
+{
+	spin_lock_init(&list_lock);
+	mutex_init(&probe_disc_mt);
+	return most_register_aim(&aim);
+}
+
+static void __exit most_net_exit(void)
+{
+	most_deregister_aim(&aim);
+}
+
+/**
+ * on_netinfo - callback for HDM to be informed about HW's MAC
+ * @param iface - most interface instance
+ * @param link_stat - link status
+ * @param mac_addr - MAC address
+ */
+static void on_netinfo(struct most_interface *iface,
+		       unsigned char link_stat, unsigned char *mac_addr)
+{
+	struct net_dev_context *nd;
+	struct net_device *dev;
+	const u8 *m = mac_addr;
+
+	nd = get_net_dev_hold(iface);
+	if (!nd)
+		return;
+
+	dev = nd->dev;
+
+	if (link_stat)
+		netif_carrier_on(dev);
+	else
+		netif_carrier_off(dev);
+
+	if (m && is_valid_ether_addr(m)) {
+		if (!is_valid_ether_addr(dev->dev_addr)) {
+			netdev_info(dev, "set mac %02x-%02x-%02x-%02x-%02x-%02x\n",
+				    m[0], m[1], m[2], m[3], m[4], m[5]);
+			ether_addr_copy(dev->dev_addr, m);
+			netif_dormant_off(dev);
+		} else if (!ether_addr_equal(dev->dev_addr, m)) {
+			netdev_warn(dev, "reject mac %02x-%02x-%02x-%02x-%02x-%02x\n",
+				    m[0], m[1], m[2], m[3], m[4], m[5]);
+		}
+	}
+
+	dev_put(nd->dev);
+}
+
+module_init(most_net_init);
+module_exit(most_net_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_DESCRIPTION("Networking Application Interface Module for MostCore");
diff --git a/drivers/staging/most/sound/Kconfig b/drivers/staging/most/sound/Kconfig
new file mode 100644
index 0000000..115262a
--- /dev/null
+++ b/drivers/staging/most/sound/Kconfig
@@ -0,0 +1,13 @@
+#
+# MOST ALSA configuration
+#
+
+config MOST_SOUND
+	tristate "Sound"
+	depends on SND
+	select SND_PCM
+	---help---
+	  Say Y here if you want to commumicate via ALSA/sound devices.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called most_sound.
diff --git a/drivers/staging/most/sound/Makefile b/drivers/staging/most/sound/Makefile
new file mode 100644
index 0000000..eee8774
--- /dev/null
+++ b/drivers/staging/most/sound/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_SOUND) += most_sound.o
+
+most_sound-objs := sound.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c
new file mode 100644
index 0000000..72603ae
--- /dev/null
+++ b/drivers/staging/most/sound/sound.c
@@ -0,0 +1,765 @@
+/*
+ * sound.c - Audio Application Interface Module for Mostcore
+ *
+ * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <most/core.h>
+
+#define DRIVER_NAME "sound"
+
+static struct list_head dev_list;
+static struct most_aim audio_aim;
+
+/**
+ * struct channel - private structure to keep channel specific data
+ * @substream: stores the substream structure
+ * @iface: interface for which the channel belongs to
+ * @cfg: channel configuration
+ * @card: registered sound card
+ * @list: list for private use
+ * @id: channel index
+ * @period_pos: current period position (ring buffer)
+ * @buffer_pos: current buffer position (ring buffer)
+ * @is_stream_running: identifies whether a stream is running or not
+ * @opened: set when the stream is opened
+ * @playback_task: playback thread
+ * @playback_waitq: waitq used by playback thread
+ */
+struct channel {
+	struct snd_pcm_substream *substream;
+	struct snd_pcm_hardware pcm_hardware;
+	struct most_interface *iface;
+	struct most_channel_config *cfg;
+	struct snd_card *card;
+	struct list_head list;
+	int id;
+	unsigned int period_pos;
+	unsigned int buffer_pos;
+	bool is_stream_running;
+
+	struct task_struct *playback_task;
+	wait_queue_head_t playback_waitq;
+
+	void (*copy_fn)(void *alsa, void *most, unsigned int bytes);
+};
+
+#define MOST_PCM_INFO (SNDRV_PCM_INFO_MMAP | \
+		       SNDRV_PCM_INFO_MMAP_VALID | \
+		       SNDRV_PCM_INFO_BATCH | \
+		       SNDRV_PCM_INFO_INTERLEAVED | \
+		       SNDRV_PCM_INFO_BLOCK_TRANSFER)
+
+#define swap16(val) ( \
+	(((u16)(val) << 8) & (u16)0xFF00) | \
+	(((u16)(val) >> 8) & (u16)0x00FF))
+
+#define swap32(val) ( \
+	(((u32)(val) << 24) & (u32)0xFF000000) | \
+	(((u32)(val) <<  8) & (u32)0x00FF0000) | \
+	(((u32)(val) >>  8) & (u32)0x0000FF00) | \
+	(((u32)(val) >> 24) & (u32)0x000000FF))
+
+static void swap_copy16(u16 *dest, const u16 *source, unsigned int bytes)
+{
+	unsigned int i = 0;
+
+	while (i < (bytes / 2)) {
+		dest[i] = swap16(source[i]);
+		i++;
+	}
+}
+
+static void swap_copy24(u8 *dest, const u8 *source, unsigned int bytes)
+{
+	unsigned int i = 0;
+
+	while (i < bytes - 2) {
+		dest[i] = source[i + 2];
+		dest[i + 1] = source[i + 1];
+		dest[i + 2] = source[i];
+		i += 3;
+	}
+}
+
+static void swap_copy32(u32 *dest, const u32 *source, unsigned int bytes)
+{
+	unsigned int i = 0;
+
+	while (i < bytes / 4) {
+		dest[i] = swap32(source[i]);
+		i++;
+	}
+}
+
+static void alsa_to_most_memcpy(void *alsa, void *most, unsigned int bytes)
+{
+	memcpy(most, alsa, bytes);
+}
+
+static void alsa_to_most_copy16(void *alsa, void *most, unsigned int bytes)
+{
+	swap_copy16(most, alsa, bytes);
+}
+
+static void alsa_to_most_copy24(void *alsa, void *most, unsigned int bytes)
+{
+	swap_copy24(most, alsa, bytes);
+}
+
+static void alsa_to_most_copy32(void *alsa, void *most, unsigned int bytes)
+{
+	swap_copy32(most, alsa, bytes);
+}
+
+static void most_to_alsa_memcpy(void *alsa, void *most, unsigned int bytes)
+{
+	memcpy(alsa, most, bytes);
+}
+
+static void most_to_alsa_copy16(void *alsa, void *most, unsigned int bytes)
+{
+	swap_copy16(alsa, most, bytes);
+}
+
+static void most_to_alsa_copy24(void *alsa, void *most, unsigned int bytes)
+{
+	swap_copy24(alsa, most, bytes);
+}
+
+static void most_to_alsa_copy32(void *alsa, void *most, unsigned int bytes)
+{
+	swap_copy32(alsa, most, bytes);
+}
+
+/**
+ * get_channel - get pointer to channel
+ * @iface: interface structure
+ * @channel_id: channel ID
+ *
+ * This traverses the channel list and returns the channel matching the
+ * ID and interface.
+ *
+ * Returns pointer to channel on success or NULL otherwise.
+ */
+static struct channel *get_channel(struct most_interface *iface,
+				   int channel_id)
+{
+	struct channel *channel, *tmp;
+
+	list_for_each_entry_safe(channel, tmp, &dev_list, list) {
+		if ((channel->iface == iface) && (channel->id == channel_id))
+			return channel;
+	}
+
+	return NULL;
+}
+
+/**
+ * copy_data - implements data copying function
+ * @channel: channel
+ * @mbo: MBO from core
+ *
+ * Copy data from/to ring buffer to/from MBO and update the buffer position
+ */
+static bool copy_data(struct channel *channel, struct mbo *mbo)
+{
+	struct snd_pcm_runtime *const runtime = channel->substream->runtime;
+	unsigned int const frame_bytes = channel->cfg->subbuffer_size;
+	unsigned int const buffer_size = runtime->buffer_size;
+	unsigned int frames;
+	unsigned int fr0;
+
+	if (channel->cfg->direction & MOST_CH_RX)
+		frames = mbo->processed_length / frame_bytes;
+	else
+		frames = mbo->buffer_length / frame_bytes;
+	fr0 = min(buffer_size - channel->buffer_pos, frames);
+
+	channel->copy_fn(runtime->dma_area + channel->buffer_pos * frame_bytes,
+			 mbo->virt_address,
+			 fr0 * frame_bytes);
+
+	if (frames > fr0) {
+		/* wrap around at end of ring buffer */
+		channel->copy_fn(runtime->dma_area,
+				 mbo->virt_address + fr0 * frame_bytes,
+				 (frames - fr0) * frame_bytes);
+	}
+
+	channel->buffer_pos += frames;
+	if (channel->buffer_pos >= buffer_size)
+		channel->buffer_pos -= buffer_size;
+	channel->period_pos += frames;
+	if (channel->period_pos >= runtime->period_size) {
+		channel->period_pos -= runtime->period_size;
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * playback_thread - function implements the playback thread
+ * @data: private data
+ *
+ * Thread which does the playback functionality in a loop. It waits for a free
+ * MBO from mostcore for a particular channel and copy the data from ring buffer
+ * to MBO. Submit the MBO back to mostcore, after copying the data.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int playback_thread(void *data)
+{
+	struct channel *const channel = data;
+
+	while (!kthread_should_stop()) {
+		struct mbo *mbo = NULL;
+		bool period_elapsed = false;
+
+		wait_event_interruptible(
+			channel->playback_waitq,
+			kthread_should_stop() ||
+			(channel->is_stream_running &&
+			 (mbo = most_get_mbo(channel->iface, channel->id,
+					     &audio_aim))));
+		if (!mbo)
+			continue;
+
+		if (channel->is_stream_running)
+			period_elapsed = copy_data(channel, mbo);
+		else
+			memset(mbo->virt_address, 0, mbo->buffer_length);
+
+		most_submit_mbo(mbo);
+		if (period_elapsed)
+			snd_pcm_period_elapsed(channel->substream);
+	}
+
+	return 0;
+}
+
+/**
+ * pcm_open - implements open callback function for PCM middle layer
+ * @substream: pointer to ALSA PCM substream
+ *
+ * This is called when a PCM substream is opened. At least, the function should
+ * initialize the runtime->hw record.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_open(struct snd_pcm_substream *substream)
+{
+	struct channel *channel = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct most_channel_config *cfg = channel->cfg;
+
+	channel->substream = substream;
+
+	if (cfg->direction == MOST_CH_TX) {
+		channel->playback_task = kthread_run(playback_thread, channel,
+						     "most_audio_playback");
+		if (IS_ERR(channel->playback_task)) {
+			pr_err("Couldn't start thread\n");
+			return PTR_ERR(channel->playback_task);
+		}
+	}
+
+	if (most_start_channel(channel->iface, channel->id, &audio_aim)) {
+		pr_err("most_start_channel() failed!\n");
+		if (cfg->direction == MOST_CH_TX)
+			kthread_stop(channel->playback_task);
+		return -EBUSY;
+	}
+
+	runtime->hw = channel->pcm_hardware;
+	return 0;
+}
+
+/**
+ * pcm_close - implements close callback function for PCM middle layer
+ * @substream: sub-stream pointer
+ *
+ * Obviously, this is called when a PCM substream is closed. Any private
+ * instance for a PCM substream allocated in the open callback will be
+ * released here.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_close(struct snd_pcm_substream *substream)
+{
+	struct channel *channel = substream->private_data;
+
+	if (channel->cfg->direction == MOST_CH_TX)
+		kthread_stop(channel->playback_task);
+	most_stop_channel(channel->iface, channel->id, &audio_aim);
+
+	return 0;
+}
+
+/**
+ * pcm_hw_params - implements hw_params callback function for PCM middle layer
+ * @substream: sub-stream pointer
+ * @hw_params: contains the hardware parameters set by the application
+ *
+ * This is called when the hardware parameters is set by the application, that
+ * is, once when the buffer size, the period size, the format, etc. are defined
+ * for the PCM substream. Many hardware setups should be done is this callback,
+ * including the allocation of buffers.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_hw_params(struct snd_pcm_substream *substream,
+			 struct snd_pcm_hw_params *hw_params)
+{
+	struct channel *channel = substream->private_data;
+
+	if ((params_channels(hw_params) > channel->pcm_hardware.channels_max) ||
+	    (params_channels(hw_params) < channel->pcm_hardware.channels_min)) {
+		pr_err("Requested number of channels not supported.\n");
+		return -EINVAL;
+	}
+	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
+						params_buffer_bytes(hw_params));
+}
+
+/**
+ * pcm_hw_free - implements hw_free callback function for PCM middle layer
+ * @substream: substream pointer
+ *
+ * This is called to release the resources allocated via hw_params.
+ * This function will be always called before the close callback is called.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+/**
+ * pcm_prepare - implements prepare callback function for PCM middle layer
+ * @substream: substream pointer
+ *
+ * This callback is called when the PCM is "prepared". Format rate, sample rate,
+ * etc., can be set here. This callback can be called many times at each setup.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct channel *channel = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct most_channel_config *cfg = channel->cfg;
+	int width = snd_pcm_format_physical_width(runtime->format);
+
+	channel->copy_fn = NULL;
+
+	if (cfg->direction == MOST_CH_TX) {
+		if (snd_pcm_format_big_endian(runtime->format) || width == 8)
+			channel->copy_fn = alsa_to_most_memcpy;
+		else if (width == 16)
+			channel->copy_fn = alsa_to_most_copy16;
+		else if (width == 24)
+			channel->copy_fn = alsa_to_most_copy24;
+		else if (width == 32)
+			channel->copy_fn = alsa_to_most_copy32;
+	} else {
+		if (snd_pcm_format_big_endian(runtime->format) || width == 8)
+			channel->copy_fn = most_to_alsa_memcpy;
+		else if (width == 16)
+			channel->copy_fn = most_to_alsa_copy16;
+		else if (width == 24)
+			channel->copy_fn = most_to_alsa_copy24;
+		else if (width == 32)
+			channel->copy_fn = most_to_alsa_copy32;
+	}
+
+	if (!channel->copy_fn) {
+		pr_err("unsupported format\n");
+		return -EINVAL;
+	}
+
+	channel->period_pos = 0;
+	channel->buffer_pos = 0;
+
+	return 0;
+}
+
+/**
+ * pcm_trigger - implements trigger callback function for PCM middle layer
+ * @substream: substream pointer
+ * @cmd: action to perform
+ *
+ * This is called when the PCM is started, stopped or paused. The action will be
+ * specified in the second argument, SNDRV_PCM_TRIGGER_XXX
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct channel *channel = substream->private_data;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		channel->is_stream_running = true;
+		wake_up_interruptible(&channel->playback_waitq);
+		return 0;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+		channel->is_stream_running = false;
+		return 0;
+
+	default:
+		pr_info("%s(), invalid\n", __func__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/**
+ * pcm_pointer - implements pointer callback function for PCM middle layer
+ * @substream: substream pointer
+ *
+ * This callback is called when the PCM middle layer inquires the current
+ * hardware position on the buffer. The position must be returned in frames,
+ * ranging from 0 to buffer_size-1.
+ */
+static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct channel *channel = substream->private_data;
+
+	return channel->buffer_pos;
+}
+
+/**
+ * Initialization of struct snd_pcm_ops
+ */
+static const struct snd_pcm_ops pcm_ops = {
+	.open       = pcm_open,
+	.close      = pcm_close,
+	.ioctl      = snd_pcm_lib_ioctl,
+	.hw_params  = pcm_hw_params,
+	.hw_free    = pcm_hw_free,
+	.prepare    = pcm_prepare,
+	.trigger    = pcm_trigger,
+	.pointer    = pcm_pointer,
+	.page       = snd_pcm_lib_get_vmalloc_page,
+	.mmap       = snd_pcm_lib_mmap_vmalloc,
+};
+
+static int split_arg_list(char *buf, char **card_name, char **pcm_format)
+{
+	*card_name = strsep(&buf, ".");
+	if (!*card_name)
+		return -EIO;
+	*pcm_format = strsep(&buf, ".\n");
+	if (!*pcm_format)
+		return -EIO;
+	return 0;
+}
+
+static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw,
+			       char *pcm_format,
+			       struct most_channel_config *cfg)
+{
+	pcm_hw->info = MOST_PCM_INFO;
+	pcm_hw->rates = SNDRV_PCM_RATE_48000;
+	pcm_hw->rate_min = 48000;
+	pcm_hw->rate_max = 48000;
+	pcm_hw->buffer_bytes_max = cfg->num_buffers * cfg->buffer_size;
+	pcm_hw->period_bytes_min = cfg->buffer_size;
+	pcm_hw->period_bytes_max = cfg->buffer_size;
+	pcm_hw->periods_min = 1;
+	pcm_hw->periods_max = cfg->num_buffers;
+
+	if (!strcmp(pcm_format, "1x8")) {
+		if (cfg->subbuffer_size != 1)
+			goto error;
+		pr_info("PCM format is 8-bit mono\n");
+		pcm_hw->channels_min = 1;
+		pcm_hw->channels_max = 1;
+		pcm_hw->formats = SNDRV_PCM_FMTBIT_S8;
+	} else if (!strcmp(pcm_format, "2x16")) {
+		if (cfg->subbuffer_size != 4)
+			goto error;
+		pr_info("PCM format is 16-bit stereo\n");
+		pcm_hw->channels_min = 2;
+		pcm_hw->channels_max = 2;
+		pcm_hw->formats = SNDRV_PCM_FMTBIT_S16_LE |
+				  SNDRV_PCM_FMTBIT_S16_BE;
+	} else if (!strcmp(pcm_format, "2x24")) {
+		if (cfg->subbuffer_size != 6)
+			goto error;
+		pr_info("PCM format is 24-bit stereo\n");
+		pcm_hw->channels_min = 2;
+		pcm_hw->channels_max = 2;
+		pcm_hw->formats = SNDRV_PCM_FMTBIT_S24_3LE |
+				  SNDRV_PCM_FMTBIT_S24_3BE;
+	} else if (!strcmp(pcm_format, "2x32")) {
+		if (cfg->subbuffer_size != 8)
+			goto error;
+		pr_info("PCM format is 32-bit stereo\n");
+		pcm_hw->channels_min = 2;
+		pcm_hw->channels_max = 2;
+		pcm_hw->formats = SNDRV_PCM_FMTBIT_S32_LE |
+				  SNDRV_PCM_FMTBIT_S32_BE;
+	} else if (!strcmp(pcm_format, "6x16")) {
+		if (cfg->subbuffer_size != 12)
+			goto error;
+		pr_info("PCM format is 16-bit 5.1 multi channel\n");
+		pcm_hw->channels_min = 6;
+		pcm_hw->channels_max = 6;
+		pcm_hw->formats = SNDRV_PCM_FMTBIT_S16_LE |
+				  SNDRV_PCM_FMTBIT_S16_BE;
+	} else {
+		pr_err("PCM format %s not supported\n", pcm_format);
+		return -EIO;
+	}
+	return 0;
+error:
+	pr_err("Audio resolution doesn't fit subbuffer size\n");
+	return -EINVAL;
+}
+
+/**
+ * audio_probe_channel - probe function of the driver module
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ * @cfg: pointer to actual channel configuration
+ * @parent: pointer to kobject (needed for sysfs hook-up)
+ * @arg_list: string that provides the name of the device to be created in /dev
+ *	      plus the desired audio resolution
+ *
+ * Creates sound card, pcm device, sets pcm ops and registers sound card.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_probe_channel(struct most_interface *iface, int channel_id,
+			       struct most_channel_config *cfg,
+			       struct kobject *parent, char *arg_list)
+{
+	struct channel *channel;
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+	int playback_count = 0;
+	int capture_count = 0;
+	int ret;
+	int direction;
+	char *card_name;
+	char *pcm_format;
+
+	if (!iface)
+		return -EINVAL;
+
+	if (cfg->data_type != MOST_CH_SYNC) {
+		pr_err("Incompatible channel type\n");
+		return -EINVAL;
+	}
+
+	if (get_channel(iface, channel_id)) {
+		pr_err("channel (%s:%d) is already linked\n",
+		       iface->description, channel_id);
+		return -EINVAL;
+	}
+
+	if (cfg->direction == MOST_CH_TX) {
+		playback_count = 1;
+		direction = SNDRV_PCM_STREAM_PLAYBACK;
+	} else {
+		capture_count = 1;
+		direction = SNDRV_PCM_STREAM_CAPTURE;
+	}
+
+	ret = split_arg_list(arg_list, &card_name, &pcm_format);
+	if (ret < 0) {
+		pr_info("PCM format missing\n");
+		return ret;
+	}
+
+	ret = snd_card_new(NULL, -1, card_name, THIS_MODULE,
+			   sizeof(*channel), &card);
+	if (ret < 0)
+		return ret;
+
+	channel = card->private_data;
+	channel->card = card;
+	channel->cfg = cfg;
+	channel->iface = iface;
+	channel->id = channel_id;
+	init_waitqueue_head(&channel->playback_waitq);
+
+	ret = audio_set_hw_params(&channel->pcm_hardware, pcm_format, cfg);
+	if (ret)
+		goto err_free_card;
+
+	snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME);
+	snprintf(card->shortname, sizeof(card->shortname), "Microchip MOST:%d",
+		 card->number);
+	snprintf(card->longname, sizeof(card->longname), "%s at %s, ch %d",
+		 card->shortname, iface->description, channel_id);
+
+	ret = snd_pcm_new(card, card_name, 0, playback_count,
+			  capture_count, &pcm);
+	if (ret < 0)
+		goto err_free_card;
+
+	pcm->private_data = channel;
+
+	snd_pcm_set_ops(pcm, direction, &pcm_ops);
+
+	ret = snd_card_register(card);
+	if (ret < 0)
+		goto err_free_card;
+
+	list_add_tail(&channel->list, &dev_list);
+
+	return 0;
+
+err_free_card:
+	snd_card_free(card);
+	return ret;
+}
+
+/**
+ * audio_disconnect_channel - function to disconnect a channel
+ * @iface: pointer to interface instance
+ * @channel_id: channel index
+ *
+ * This frees allocated memory and removes the sound card from ALSA
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_disconnect_channel(struct most_interface *iface,
+				    int channel_id)
+{
+	struct channel *channel;
+
+	channel = get_channel(iface, channel_id);
+	if (!channel) {
+		pr_err("sound_disconnect_channel(), invalid channel %d\n",
+		       channel_id);
+		return -EINVAL;
+	}
+
+	list_del(&channel->list);
+	snd_card_free(channel->card);
+
+	return 0;
+}
+
+/**
+ * audio_rx_completion - completion handler for rx channels
+ * @mbo: pointer to buffer object that has completed
+ *
+ * This searches for the channel this MBO belongs to and copy the data from MBO
+ * to ring buffer
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_rx_completion(struct mbo *mbo)
+{
+	struct channel *channel = get_channel(mbo->ifp, mbo->hdm_channel_id);
+	bool period_elapsed = false;
+
+	if (!channel) {
+		pr_err("sound_rx_completion(), invalid channel %d\n",
+		       mbo->hdm_channel_id);
+		return -EINVAL;
+	}
+
+	if (channel->is_stream_running)
+		period_elapsed = copy_data(channel, mbo);
+
+	most_put_mbo(mbo);
+
+	if (period_elapsed)
+		snd_pcm_period_elapsed(channel->substream);
+
+	return 0;
+}
+
+/**
+ * audio_tx_completion - completion handler for tx channels
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ *
+ * This searches the channel that belongs to this combination of interface
+ * pointer and channel ID and wakes a process sitting in the wait queue of
+ * this channel.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_tx_completion(struct most_interface *iface, int channel_id)
+{
+	struct channel *channel = get_channel(iface, channel_id);
+
+	if (!channel) {
+		pr_err("sound_tx_completion(), invalid channel %d\n",
+		       channel_id);
+		return -EINVAL;
+	}
+
+	wake_up_interruptible(&channel->playback_waitq);
+
+	return 0;
+}
+
+/**
+ * Initialization of the struct most_aim
+ */
+static struct most_aim audio_aim = {
+	.name = DRIVER_NAME,
+	.probe_channel = audio_probe_channel,
+	.disconnect_channel = audio_disconnect_channel,
+	.rx_completion = audio_rx_completion,
+	.tx_completion = audio_tx_completion,
+};
+
+static int __init audio_init(void)
+{
+	pr_info("init()\n");
+
+	INIT_LIST_HEAD(&dev_list);
+
+	return most_register_aim(&audio_aim);
+}
+
+static void __exit audio_exit(void)
+{
+	struct channel *channel, *tmp;
+
+	pr_info("exit()\n");
+
+	list_for_each_entry_safe(channel, tmp, &dev_list, list) {
+		list_del(&channel->list);
+		snd_card_free(channel->card);
+	}
+
+	most_deregister_aim(&audio_aim);
+}
+
+module_init(audio_init);
+module_exit(audio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_DESCRIPTION("Audio Application Interface Module for MostCore");
diff --git a/drivers/staging/most/usb/Kconfig b/drivers/staging/most/usb/Kconfig
new file mode 100644
index 0000000..ebbdb57
--- /dev/null
+++ b/drivers/staging/most/usb/Kconfig
@@ -0,0 +1,13 @@
+#
+# MOST USB configuration
+#
+
+config MOST_USB
+	tristate "USB"
+	depends on USB && NET
+	---help---
+	  Say Y here if you want to connect via USB to network tranceiver.
+	  This device driver depends on the networking AIM.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called most_usb.
diff --git a/drivers/staging/most/usb/Makefile b/drivers/staging/most/usb/Makefile
new file mode 100644
index 0000000..18d28cb
--- /dev/null
+++ b/drivers/staging/most/usb/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_USB) += most_usb.o
+
+most_usb-objs := usb.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c
new file mode 100644
index 0000000..2e4f237
--- /dev/null
+++ b/drivers/staging/most/usb/usb.c
@@ -0,0 +1,1307 @@
+/*
+ * usb.c - Hardware dependent module for USB
+ *
+ * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/uaccess.h>
+#include <most/core.h>
+
+#define USB_MTU			512
+#define NO_ISOCHRONOUS_URB	0
+#define AV_PACKETS_PER_XACT	2
+#define BUF_CHAIN_SIZE		0xFFFF
+#define MAX_NUM_ENDPOINTS	30
+#define MAX_SUFFIX_LEN		10
+#define MAX_STRING_LEN		80
+#define MAX_BUF_SIZE		0xFFFF
+
+#define USB_VENDOR_ID_SMSC	0x0424  /* VID: SMSC */
+#define USB_DEV_ID_BRDG		0xC001  /* PID: USB Bridge */
+#define USB_DEV_ID_OS81118	0xCF18  /* PID: USB OS81118 */
+#define USB_DEV_ID_OS81119	0xCF19  /* PID: USB OS81119 */
+#define USB_DEV_ID_OS81210	0xCF30  /* PID: USB OS81210 */
+/* DRCI Addresses */
+#define DRCI_REG_NI_STATE	0x0100
+#define DRCI_REG_PACKET_BW	0x0101
+#define DRCI_REG_NODE_ADDR	0x0102
+#define DRCI_REG_NODE_POS	0x0103
+#define DRCI_REG_MEP_FILTER	0x0140
+#define DRCI_REG_HASH_TBL0	0x0141
+#define DRCI_REG_HASH_TBL1	0x0142
+#define DRCI_REG_HASH_TBL2	0x0143
+#define DRCI_REG_HASH_TBL3	0x0144
+#define DRCI_REG_HW_ADDR_HI	0x0145
+#define DRCI_REG_HW_ADDR_MI	0x0146
+#define DRCI_REG_HW_ADDR_LO	0x0147
+#define DRCI_REG_BASE		0x1100
+#define DRCI_COMMAND		0x02
+#define DRCI_READ_REQ		0xA0
+#define DRCI_WRITE_REQ		0xA1
+
+/**
+ * struct most_dci_obj - Direct Communication Interface
+ * @kobj:position in sysfs
+ * @usb_device: pointer to the usb device
+ * @reg_addr: register address for arbitrary DCI access
+ */
+struct most_dci_obj {
+	struct kobject kobj;
+	struct usb_device *usb_device;
+	u16 reg_addr;
+};
+
+#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj)
+
+struct most_dev;
+
+struct clear_hold_work {
+	struct work_struct ws;
+	struct most_dev *mdev;
+	unsigned int channel;
+	int pipe;
+};
+
+#define to_clear_hold_work(w) container_of(w, struct clear_hold_work, ws)
+
+/**
+ * struct most_dev - holds all usb interface specific stuff
+ * @parent: parent object in sysfs
+ * @usb_device: pointer to usb device
+ * @iface: hardware interface
+ * @cap: channel capabilities
+ * @conf: channel configuration
+ * @dci: direct communication interface of hardware
+ * @ep_address: endpoint address table
+ * @description: device description
+ * @suffix: suffix for channel name
+ * @channel_lock: synchronize channel access
+ * @padding_active: indicates channel uses padding
+ * @is_channel_healthy: health status table of each channel
+ * @busy_urbs: list of anchored items
+ * @io_mutex: synchronize I/O with disconnect
+ * @link_stat_timer: timer for link status reports
+ * @poll_work_obj: work for polling link status
+ */
+struct most_dev {
+	struct kobject *parent;
+	struct usb_device *usb_device;
+	struct most_interface iface;
+	struct most_channel_capability *cap;
+	struct most_channel_config *conf;
+	struct most_dci_obj *dci;
+	u8 *ep_address;
+	char description[MAX_STRING_LEN];
+	char suffix[MAX_NUM_ENDPOINTS][MAX_SUFFIX_LEN];
+	spinlock_t channel_lock[MAX_NUM_ENDPOINTS]; /* sync channel access */
+	bool padding_active[MAX_NUM_ENDPOINTS];
+	bool is_channel_healthy[MAX_NUM_ENDPOINTS];
+	struct clear_hold_work clear_work[MAX_NUM_ENDPOINTS];
+	struct usb_anchor *busy_urbs;
+	struct mutex io_mutex;
+	struct timer_list link_stat_timer;
+	struct work_struct poll_work_obj;
+	void (*on_netinfo)(struct most_interface *, unsigned char,
+			   unsigned char *);
+};
+
+#define to_mdev(d) container_of(d, struct most_dev, iface)
+#define to_mdev_from_work(w) container_of(w, struct most_dev, poll_work_obj)
+
+static void wq_clear_halt(struct work_struct *wq_obj);
+static void wq_netinfo(struct work_struct *wq_obj);
+
+/**
+ * drci_rd_reg - read a DCI register
+ * @dev: usb device
+ * @reg: register address
+ * @buf: buffer to store data
+ *
+ * This is reads data from INIC's direct register communication interface
+ */
+static inline int drci_rd_reg(struct usb_device *dev, u16 reg, u16 *buf)
+{
+	int retval;
+	__le16 *dma_buf = kzalloc(sizeof(*dma_buf), GFP_KERNEL);
+	u8 req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+
+	if (!dma_buf)
+		return -ENOMEM;
+
+	retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+				 DRCI_READ_REQ, req_type,
+				 0x0000,
+				 reg, dma_buf, sizeof(*dma_buf), 5 * HZ);
+	*buf = le16_to_cpu(*dma_buf);
+	kfree(dma_buf);
+
+	return retval;
+}
+
+/**
+ * drci_wr_reg - write a DCI register
+ * @dev: usb device
+ * @reg: register address
+ * @data: data to write
+ *
+ * This is writes data to INIC's direct register communication interface
+ */
+static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data)
+{
+	return usb_control_msg(dev,
+			       usb_sndctrlpipe(dev, 0),
+			       DRCI_WRITE_REQ,
+			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			       data,
+			       reg,
+			       NULL,
+			       0,
+			       5 * HZ);
+}
+
+static inline int start_sync_ep(struct usb_device *usb_dev, u16 ep)
+{
+	return drci_wr_reg(usb_dev, DRCI_REG_BASE + DRCI_COMMAND + ep * 16, 1);
+}
+
+/**
+ * get_stream_frame_size - calculate frame size of current configuration
+ * @cfg: channel configuration
+ */
+static unsigned int get_stream_frame_size(struct most_channel_config *cfg)
+{
+	unsigned int frame_size = 0;
+	unsigned int sub_size = cfg->subbuffer_size;
+
+	if (!sub_size) {
+		pr_warn("Misconfig: Subbuffer size zero.\n");
+		return frame_size;
+	}
+	switch (cfg->data_type) {
+	case MOST_CH_ISOC:
+		frame_size = AV_PACKETS_PER_XACT * sub_size;
+		break;
+	case MOST_CH_SYNC:
+		if (cfg->packets_per_xact == 0) {
+			pr_warn("Misconfig: Packets per XACT zero\n");
+			frame_size = 0;
+		} else if (cfg->packets_per_xact == 0xFF) {
+			frame_size = (USB_MTU / sub_size) * sub_size;
+		} else {
+			frame_size = cfg->packets_per_xact * sub_size;
+		}
+		break;
+	default:
+		pr_warn("Query frame size of non-streaming channel\n");
+		break;
+	}
+	return frame_size;
+}
+
+/**
+ * hdm_poison_channel - mark buffers of this channel as invalid
+ * @iface: pointer to the interface
+ * @channel: channel ID
+ *
+ * This unlinks all URBs submitted to the HCD,
+ * calls the associated completion function of the core and removes
+ * them from the list.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int hdm_poison_channel(struct most_interface *iface, int channel)
+{
+	struct most_dev *mdev = to_mdev(iface);
+	unsigned long flags;
+	spinlock_t *lock; /* temp. lock */
+
+	if (unlikely(!iface)) {
+		dev_warn(&mdev->usb_device->dev, "Poison: Bad interface.\n");
+		return -EIO;
+	}
+	if (unlikely(channel < 0 || channel >= iface->num_channels)) {
+		dev_warn(&mdev->usb_device->dev, "Channel ID out of range.\n");
+		return -ECHRNG;
+	}
+
+	lock = mdev->channel_lock + channel;
+	spin_lock_irqsave(lock, flags);
+	mdev->is_channel_healthy[channel] = false;
+	spin_unlock_irqrestore(lock, flags);
+
+	cancel_work_sync(&mdev->clear_work[channel].ws);
+
+	mutex_lock(&mdev->io_mutex);
+	usb_kill_anchored_urbs(&mdev->busy_urbs[channel]);
+	if (mdev->padding_active[channel])
+		mdev->padding_active[channel] = false;
+
+	if (mdev->conf[channel].data_type == MOST_CH_ASYNC) {
+		del_timer_sync(&mdev->link_stat_timer);
+		cancel_work_sync(&mdev->poll_work_obj);
+	}
+	mutex_unlock(&mdev->io_mutex);
+	return 0;
+}
+
+/**
+ * hdm_add_padding - add padding bytes
+ * @mdev: most device
+ * @channel: channel ID
+ * @mbo: buffer object
+ *
+ * This inserts the INIC hardware specific padding bytes into a streaming
+ * channel's buffer
+ */
+static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo)
+{
+	struct most_channel_config *conf = &mdev->conf[channel];
+	unsigned int frame_size = get_stream_frame_size(conf);
+	unsigned int j, num_frames;
+
+	if (!frame_size)
+		return -EIO;
+	num_frames = mbo->buffer_length / frame_size;
+
+	if (num_frames < 1) {
+		dev_err(&mdev->usb_device->dev,
+			"Missed minimal transfer unit.\n");
+		return -EIO;
+	}
+
+	for (j = num_frames - 1; j > 0; j--)
+		memmove(mbo->virt_address + j * USB_MTU,
+			mbo->virt_address + j * frame_size,
+			frame_size);
+	mbo->buffer_length = num_frames * USB_MTU;
+	return 0;
+}
+
+/**
+ * hdm_remove_padding - remove padding bytes
+ * @mdev: most device
+ * @channel: channel ID
+ * @mbo: buffer object
+ *
+ * This takes the INIC hardware specific padding bytes off a streaming
+ * channel's buffer.
+ */
+static int hdm_remove_padding(struct most_dev *mdev, int channel,
+			      struct mbo *mbo)
+{
+	struct most_channel_config *const conf = &mdev->conf[channel];
+	unsigned int frame_size = get_stream_frame_size(conf);
+	unsigned int j, num_frames;
+
+	if (!frame_size)
+		return -EIO;
+	num_frames = mbo->processed_length / USB_MTU;
+
+	for (j = 1; j < num_frames; j++)
+		memmove(mbo->virt_address + frame_size * j,
+			mbo->virt_address + USB_MTU * j,
+			frame_size);
+
+	mbo->processed_length = frame_size * num_frames;
+	return 0;
+}
+
+/**
+ * hdm_write_completion - completion function for submitted Tx URBs
+ * @urb: the URB that has been completed
+ *
+ * This checks the status of the completed URB. In case the URB has been
+ * unlinked before, it is immediately freed. On any other error the MBO
+ * transfer flag is set. On success it frees allocated resources and calls
+ * the completion function.
+ *
+ * Context: interrupt!
+ */
+static void hdm_write_completion(struct urb *urb)
+{
+	struct mbo *mbo = urb->context;
+	struct most_dev *mdev = to_mdev(mbo->ifp);
+	unsigned int channel = mbo->hdm_channel_id;
+	struct device *dev = &mdev->usb_device->dev;
+	spinlock_t *lock = mdev->channel_lock + channel;
+	unsigned long flags;
+
+	spin_lock_irqsave(lock, flags);
+
+	mbo->processed_length = 0;
+	mbo->status = MBO_E_INVAL;
+	if (likely(mdev->is_channel_healthy[channel])) {
+		switch (urb->status) {
+		case 0:
+		case -ESHUTDOWN:
+			mbo->processed_length = urb->actual_length;
+			mbo->status = MBO_SUCCESS;
+			break;
+		case -EPIPE:
+			dev_warn(dev, "Broken OUT pipe detected\n");
+			mdev->is_channel_healthy[channel] = false;
+			mdev->clear_work[channel].pipe = urb->pipe;
+			schedule_work(&mdev->clear_work[channel].ws);
+			break;
+		case -ENODEV:
+		case -EPROTO:
+			mbo->status = MBO_E_CLOSE;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(lock, flags);
+
+	if (likely(mbo->complete))
+		mbo->complete(mbo);
+	usb_free_urb(urb);
+}
+
+/**
+ * hdm_read_completion - completion function for submitted Rx URBs
+ * @urb: the URB that has been completed
+ *
+ * This checks the status of the completed URB. In case the URB has been
+ * unlinked before it is immediately freed. On any other error the MBO transfer
+ * flag is set. On success it frees allocated resources, removes
+ * padding bytes -if necessary- and calls the completion function.
+ *
+ * Context: interrupt!
+ *
+ * **************************************************************************
+ *                   Error codes returned by in urb->status
+ *                   or in iso_frame_desc[n].status (for ISO)
+ * *************************************************************************
+ *
+ * USB device drivers may only test urb status values in completion handlers.
+ * This is because otherwise there would be a race between HCDs updating
+ * these values on one CPU, and device drivers testing them on another CPU.
+ *
+ * A transfer's actual_length may be positive even when an error has been
+ * reported.  That's because transfers often involve several packets, so that
+ * one or more packets could finish before an error stops further endpoint I/O.
+ *
+ * For isochronous URBs, the urb status value is non-zero only if the URB is
+ * unlinked, the device is removed, the host controller is disabled or the total
+ * transferred length is less than the requested length and the URB_SHORT_NOT_OK
+ * flag is set.  Completion handlers for isochronous URBs should only see
+ * urb->status set to zero, -ENOENT, -ECONNRESET, -ESHUTDOWN, or -EREMOTEIO.
+ * Individual frame descriptor status fields may report more status codes.
+ *
+ *
+ * 0			Transfer completed successfully
+ *
+ * -ENOENT		URB was synchronously unlinked by usb_unlink_urb
+ *
+ * -EINPROGRESS		URB still pending, no results yet
+ *			(That is, if drivers see this it's a bug.)
+ *
+ * -EPROTO (*, **)	a) bitstuff error
+ *			b) no response packet received within the
+ *			   prescribed bus turn-around time
+ *			c) unknown USB error
+ *
+ * -EILSEQ (*, **)	a) CRC mismatch
+ *			b) no response packet received within the
+ *			   prescribed bus turn-around time
+ *			c) unknown USB error
+ *
+ *			Note that often the controller hardware does not
+ *			distinguish among cases a), b), and c), so a
+ *			driver cannot tell whether there was a protocol
+ *			error, a failure to respond (often caused by
+ *			device disconnect), or some other fault.
+ *
+ * -ETIME (**)		No response packet received within the prescribed
+ *			bus turn-around time.  This error may instead be
+ *			reported as -EPROTO or -EILSEQ.
+ *
+ * -ETIMEDOUT		Synchronous USB message functions use this code
+ *			to indicate timeout expired before the transfer
+ *			completed, and no other error was reported by HC.
+ *
+ * -EPIPE (**)		Endpoint stalled.  For non-control endpoints,
+ *			reset this status with usb_clear_halt().
+ *
+ * -ECOMM		During an IN transfer, the host controller
+ *			received data from an endpoint faster than it
+ *			could be written to system memory
+ *
+ * -ENOSR		During an OUT transfer, the host controller
+ *			could not retrieve data from system memory fast
+ *			enough to keep up with the USB data rate
+ *
+ * -EOVERFLOW (*)	The amount of data returned by the endpoint was
+ *			greater than either the max packet size of the
+ *			endpoint or the remaining buffer size.  "Babble".
+ *
+ * -EREMOTEIO		The data read from the endpoint did not fill the
+ *			specified buffer, and URB_SHORT_NOT_OK was set in
+ *			urb->transfer_flags.
+ *
+ * -ENODEV		Device was removed.  Often preceded by a burst of
+ *			other errors, since the hub driver doesn't detect
+ *			device removal events immediately.
+ *
+ * -EXDEV		ISO transfer only partially completed
+ *			(only set in iso_frame_desc[n].status, not urb->status)
+ *
+ * -EINVAL		ISO madness, if this happens: Log off and go home
+ *
+ * -ECONNRESET		URB was asynchronously unlinked by usb_unlink_urb
+ *
+ * -ESHUTDOWN		The device or host controller has been disabled due
+ *			to some problem that could not be worked around,
+ *			such as a physical disconnect.
+ *
+ *
+ * (*) Error codes like -EPROTO, -EILSEQ and -EOVERFLOW normally indicate
+ * hardware problems such as bad devices (including firmware) or cables.
+ *
+ * (**) This is also one of several codes that different kinds of host
+ * controller use to indicate a transfer has failed because of device
+ * disconnect.  In the interval before the hub driver starts disconnect
+ * processing, devices may receive such fault reports for every request.
+ *
+ * See <https://www.kernel.org/doc/Documentation/driver-api/usb/error-codes.rst>
+ */
+static void hdm_read_completion(struct urb *urb)
+{
+	struct mbo *mbo = urb->context;
+	struct most_dev *mdev = to_mdev(mbo->ifp);
+	unsigned int channel = mbo->hdm_channel_id;
+	struct device *dev = &mdev->usb_device->dev;
+	spinlock_t *lock = mdev->channel_lock + channel;
+	unsigned long flags;
+
+	spin_lock_irqsave(lock, flags);
+
+	mbo->processed_length = 0;
+	mbo->status = MBO_E_INVAL;
+	if (likely(mdev->is_channel_healthy[channel])) {
+		switch (urb->status) {
+		case 0:
+		case -ESHUTDOWN:
+			mbo->processed_length = urb->actual_length;
+			mbo->status = MBO_SUCCESS;
+			if (mdev->padding_active[channel] &&
+			    hdm_remove_padding(mdev, channel, mbo)) {
+				mbo->processed_length = 0;
+				mbo->status = MBO_E_INVAL;
+			}
+			break;
+		case -EPIPE:
+			dev_warn(dev, "Broken IN pipe detected\n");
+			mdev->is_channel_healthy[channel] = false;
+			mdev->clear_work[channel].pipe = urb->pipe;
+			schedule_work(&mdev->clear_work[channel].ws);
+			break;
+		case -ENODEV:
+		case -EPROTO:
+			mbo->status = MBO_E_CLOSE;
+			break;
+		case -EOVERFLOW:
+			dev_warn(dev, "Babble on IN pipe detected\n");
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(lock, flags);
+
+	if (likely(mbo->complete))
+		mbo->complete(mbo);
+	usb_free_urb(urb);
+}
+
+/**
+ * hdm_enqueue - receive a buffer to be used for data transfer
+ * @iface: interface to enqueue to
+ * @channel: ID of the channel
+ * @mbo: pointer to the buffer object
+ *
+ * This allocates a new URB and fills it according to the channel
+ * that is being used for transmission of data. Before the URB is
+ * submitted it is stored in the private anchor list.
+ *
+ * Returns 0 on success. On any error the URB is freed and a error code
+ * is returned.
+ *
+ * Context: Could in _some_ cases be interrupt!
+ */
+static int hdm_enqueue(struct most_interface *iface, int channel,
+		       struct mbo *mbo)
+{
+	struct most_dev *mdev;
+	struct most_channel_config *conf;
+	struct device *dev;
+	int retval = 0;
+	struct urb *urb;
+	unsigned long length;
+	void *virt_address;
+
+	if (unlikely(!iface || !mbo))
+		return -EIO;
+	if (unlikely(iface->num_channels <= channel || channel < 0))
+		return -ECHRNG;
+
+	mdev = to_mdev(iface);
+	conf = &mdev->conf[channel];
+	dev = &mdev->usb_device->dev;
+
+	if (!mdev->usb_device)
+		return -ENODEV;
+
+	urb = usb_alloc_urb(NO_ISOCHRONOUS_URB, GFP_ATOMIC);
+	if (!urb)
+		return -ENOMEM;
+
+	if ((conf->direction & MOST_CH_TX) && mdev->padding_active[channel] &&
+	    hdm_add_padding(mdev, channel, mbo)) {
+		retval = -EIO;
+		goto _error;
+	}
+
+	urb->transfer_dma = mbo->bus_address;
+	virt_address = mbo->virt_address;
+	length = mbo->buffer_length;
+
+	if (conf->direction & MOST_CH_TX) {
+		usb_fill_bulk_urb(urb, mdev->usb_device,
+				  usb_sndbulkpipe(mdev->usb_device,
+						  mdev->ep_address[channel]),
+				  virt_address,
+				  length,
+				  hdm_write_completion,
+				  mbo);
+		if (conf->data_type != MOST_CH_ISOC)
+			urb->transfer_flags |= URB_ZERO_PACKET;
+	} else {
+		usb_fill_bulk_urb(urb, mdev->usb_device,
+				  usb_rcvbulkpipe(mdev->usb_device,
+						  mdev->ep_address[channel]),
+				  virt_address,
+				  length + conf->extra_len,
+				  hdm_read_completion,
+				  mbo);
+	}
+	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	usb_anchor_urb(urb, &mdev->busy_urbs[channel]);
+
+	retval = usb_submit_urb(urb, GFP_KERNEL);
+	if (retval) {
+		dev_err(dev, "URB submit failed with error %d.\n", retval);
+		goto _error_1;
+	}
+	return 0;
+
+_error_1:
+	usb_unanchor_urb(urb);
+_error:
+	usb_free_urb(urb);
+	return retval;
+}
+
+/**
+ * hdm_configure_channel - receive channel configuration from core
+ * @iface: interface
+ * @channel: channel ID
+ * @conf: structure that holds the configuration information
+ *
+ * The attached network interface controller (NIC) supports a padding mode
+ * to avoid short packets on USB, hence increasing the performance due to a
+ * lower interrupt load. This mode is default for synchronous data and can
+ * be switched on for isochronous data. In case padding is active the
+ * driver needs to know the frame size of the payload in order to calculate
+ * the number of bytes it needs to pad when transmitting or to cut off when
+ * receiving data.
+ *
+ */
+static int hdm_configure_channel(struct most_interface *iface, int channel,
+				 struct most_channel_config *conf)
+{
+	unsigned int num_frames;
+	unsigned int frame_size;
+	struct most_dev *mdev = to_mdev(iface);
+	struct device *dev = &mdev->usb_device->dev;
+
+	mdev->is_channel_healthy[channel] = true;
+	mdev->clear_work[channel].channel = channel;
+	mdev->clear_work[channel].mdev = mdev;
+	INIT_WORK(&mdev->clear_work[channel].ws, wq_clear_halt);
+
+	if (unlikely(!iface || !conf)) {
+		dev_err(dev, "Bad interface or config pointer.\n");
+		return -EINVAL;
+	}
+	if (unlikely(channel < 0 || channel >= iface->num_channels)) {
+		dev_err(dev, "Channel ID out of range.\n");
+		return -EINVAL;
+	}
+	if (!conf->num_buffers || !conf->buffer_size) {
+		dev_err(dev, "Misconfig: buffer size or #buffers zero.\n");
+		return -EINVAL;
+	}
+
+	if (conf->data_type != MOST_CH_SYNC &&
+	    !(conf->data_type == MOST_CH_ISOC &&
+	      conf->packets_per_xact != 0xFF)) {
+		mdev->padding_active[channel] = false;
+		/*
+		 * Since the NIC's padding mode is not going to be
+		 * used, we can skip the frame size calculations and
+		 * move directly on to exit.
+		 */
+		goto exit;
+	}
+
+	mdev->padding_active[channel] = true;
+
+	frame_size = get_stream_frame_size(conf);
+	if (frame_size == 0 || frame_size > USB_MTU) {
+		dev_warn(dev, "Misconfig: frame size wrong\n");
+		return -EINVAL;
+	}
+
+	num_frames = conf->buffer_size / frame_size;
+
+	if (conf->buffer_size % frame_size) {
+		u16 old_size = conf->buffer_size;
+
+		conf->buffer_size = num_frames * frame_size;
+		dev_warn(dev, "%s: fixed buffer size (%d -> %d)\n",
+			 mdev->suffix[channel], old_size, conf->buffer_size);
+	}
+
+	/* calculate extra length to comply w/ HW padding */
+	conf->extra_len = num_frames * (USB_MTU - frame_size);
+
+exit:
+	mdev->conf[channel] = *conf;
+	if (conf->data_type == MOST_CH_ASYNC) {
+		u16 ep = mdev->ep_address[channel];
+
+		if (start_sync_ep(mdev->usb_device, ep) < 0)
+			dev_warn(dev, "sync for ep%02x failed", ep);
+	}
+	return 0;
+}
+
+/**
+ * hdm_request_netinfo - request network information
+ * @iface: pointer to interface
+ * @channel: channel ID
+ *
+ * This is used as trigger to set up the link status timer that
+ * polls for the NI state of the INIC every 2 seconds.
+ *
+ */
+static void hdm_request_netinfo(struct most_interface *iface, int channel,
+				void (*on_netinfo)(struct most_interface *,
+						   unsigned char,
+						   unsigned char *))
+{
+	struct most_dev *mdev;
+
+	BUG_ON(!iface);
+	mdev = to_mdev(iface);
+	mdev->on_netinfo = on_netinfo;
+	if (!on_netinfo)
+		return;
+
+	mdev->link_stat_timer.expires = jiffies + HZ;
+	mod_timer(&mdev->link_stat_timer, mdev->link_stat_timer.expires);
+}
+
+/**
+ * link_stat_timer_handler - schedule work obtaining mac address and link status
+ * @data: pointer to USB device instance
+ *
+ * The handler runs in interrupt context. That's why we need to defer the
+ * tasks to a work queue.
+ */
+static void link_stat_timer_handler(unsigned long data)
+{
+	struct most_dev *mdev = (struct most_dev *)data;
+
+	schedule_work(&mdev->poll_work_obj);
+	mdev->link_stat_timer.expires = jiffies + (2 * HZ);
+	add_timer(&mdev->link_stat_timer);
+}
+
+/**
+ * wq_netinfo - work queue function to deliver latest networking information
+ * @wq_obj: object that holds data for our deferred work to do
+ *
+ * This retrieves the network interface status of the USB INIC
+ */
+static void wq_netinfo(struct work_struct *wq_obj)
+{
+	struct most_dev *mdev = to_mdev_from_work(wq_obj);
+	struct usb_device *usb_device = mdev->usb_device;
+	struct device *dev = &usb_device->dev;
+	u16 hi, mi, lo, link;
+	u8 hw_addr[6];
+
+	if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_HI, &hi) < 0) {
+		dev_err(dev, "Vendor request 'hw_addr_hi' failed\n");
+		return;
+	}
+
+	if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_MI, &mi) < 0) {
+		dev_err(dev, "Vendor request 'hw_addr_mid' failed\n");
+		return;
+	}
+
+	if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_LO, &lo) < 0) {
+		dev_err(dev, "Vendor request 'hw_addr_low' failed\n");
+		return;
+	}
+
+	if (drci_rd_reg(usb_device, DRCI_REG_NI_STATE, &link) < 0) {
+		dev_err(dev, "Vendor request 'link status' failed\n");
+		return;
+	}
+
+	hw_addr[0] = hi >> 8;
+	hw_addr[1] = hi;
+	hw_addr[2] = mi >> 8;
+	hw_addr[3] = mi;
+	hw_addr[4] = lo >> 8;
+	hw_addr[5] = lo;
+
+	if (mdev->on_netinfo)
+		mdev->on_netinfo(&mdev->iface, link, hw_addr);
+}
+
+/**
+ * wq_clear_halt - work queue function
+ * @wq_obj: work_struct object to execute
+ *
+ * This sends a clear_halt to the given USB pipe.
+ */
+static void wq_clear_halt(struct work_struct *wq_obj)
+{
+	struct clear_hold_work *clear_work = to_clear_hold_work(wq_obj);
+	struct most_dev *mdev = clear_work->mdev;
+	unsigned int channel = clear_work->channel;
+	int pipe = clear_work->pipe;
+
+	mutex_lock(&mdev->io_mutex);
+	most_stop_enqueue(&mdev->iface, channel);
+	usb_kill_anchored_urbs(&mdev->busy_urbs[channel]);
+	if (usb_clear_halt(mdev->usb_device, pipe))
+		dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n");
+
+	mdev->is_channel_healthy[channel] = true;
+	most_resume_enqueue(&mdev->iface, channel);
+	mutex_unlock(&mdev->io_mutex);
+}
+
+/**
+ * hdm_usb_fops - file operation table for USB driver
+ */
+static const struct file_operations hdm_usb_fops = {
+	.owner = THIS_MODULE,
+};
+
+/**
+ * usb_device_id - ID table for HCD device probing
+ */
+static const struct usb_device_id usbid[] = {
+	{ USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), },
+	{ USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81118), },
+	{ USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81119), },
+	{ USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_OS81210), },
+	{ } /* Terminating entry */
+};
+
+#define MOST_DCI_RO_ATTR(_name) \
+	struct most_dci_attribute most_dci_attr_##_name = \
+		__ATTR(_name, 0444, show_value, NULL)
+
+#define MOST_DCI_ATTR(_name) \
+	struct most_dci_attribute most_dci_attr_##_name = \
+		__ATTR(_name, 0644, show_value, store_value)
+
+#define MOST_DCI_WO_ATTR(_name) \
+	struct most_dci_attribute most_dci_attr_##_name = \
+		__ATTR(_name, 0200, NULL, store_value)
+
+/**
+ * struct most_dci_attribute - to access the attributes of a dci object
+ * @attr: attributes of a dci object
+ * @show: pointer to the show function
+ * @store: pointer to the store function
+ */
+struct most_dci_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct most_dci_obj *d,
+			struct most_dci_attribute *attr,
+			char *buf);
+	ssize_t (*store)(struct most_dci_obj *d,
+			 struct most_dci_attribute *attr,
+			 const char *buf,
+			 size_t count);
+};
+
+#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr)
+
+/**
+ * dci_attr_show - show function for dci object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ */
+static ssize_t dci_attr_show(struct kobject *kobj, struct attribute *attr,
+			     char *buf)
+{
+	struct most_dci_attribute *dci_attr = to_dci_attr(attr);
+	struct most_dci_obj *dci_obj = to_dci_obj(kobj);
+
+	if (!dci_attr->show)
+		return -EIO;
+
+	return dci_attr->show(dci_obj, dci_attr, buf);
+}
+
+/**
+ * dci_attr_store - store function for dci object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ * @len: length of buffer
+ */
+static ssize_t dci_attr_store(struct kobject *kobj,
+			      struct attribute *attr,
+			      const char *buf,
+			      size_t len)
+{
+	struct most_dci_attribute *dci_attr = to_dci_attr(attr);
+	struct most_dci_obj *dci_obj = to_dci_obj(kobj);
+
+	if (!dci_attr->store)
+		return -EIO;
+
+	return dci_attr->store(dci_obj, dci_attr, buf, len);
+}
+
+static const struct sysfs_ops most_dci_sysfs_ops = {
+	.show = dci_attr_show,
+	.store = dci_attr_store,
+};
+
+/**
+ * most_dci_release - release function for dci object
+ * @kobj: pointer to kobject
+ *
+ * This frees the memory allocated for the dci object
+ */
+static void most_dci_release(struct kobject *kobj)
+{
+	struct most_dci_obj *dci_obj = to_dci_obj(kobj);
+
+	kfree(dci_obj);
+}
+
+struct regs {
+	const char *name;
+	u16 reg;
+};
+
+static const struct regs ro_regs[] = {
+	{ "ni_state", DRCI_REG_NI_STATE },
+	{ "packet_bandwidth", DRCI_REG_PACKET_BW },
+	{ "node_address", DRCI_REG_NODE_ADDR },
+	{ "node_position", DRCI_REG_NODE_POS },
+};
+
+static const struct regs rw_regs[] = {
+	{ "mep_filter", DRCI_REG_MEP_FILTER },
+	{ "mep_hash0", DRCI_REG_HASH_TBL0 },
+	{ "mep_hash1", DRCI_REG_HASH_TBL1 },
+	{ "mep_hash2", DRCI_REG_HASH_TBL2 },
+	{ "mep_hash3", DRCI_REG_HASH_TBL3 },
+	{ "mep_eui48_hi", DRCI_REG_HW_ADDR_HI },
+	{ "mep_eui48_mi", DRCI_REG_HW_ADDR_MI },
+	{ "mep_eui48_lo", DRCI_REG_HW_ADDR_LO },
+};
+
+static int get_stat_reg_addr(const struct regs *regs, int size,
+			     const char *name, u16 *reg_addr)
+{
+	int i;
+
+	for (i = 0; i < size; i++) {
+		if (!strcmp(name, regs[i].name)) {
+			*reg_addr = regs[i].reg;
+			return 0;
+		}
+	}
+	return -EFAULT;
+}
+
+#define get_static_reg_addr(regs, name, reg_addr) \
+	get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr)
+
+static ssize_t show_value(struct most_dci_obj *dci_obj,
+			  struct most_dci_attribute *attr, char *buf)
+{
+	const char *name = attr->attr.name;
+	u16 val;
+	u16 reg_addr;
+	int err;
+
+	if (!strcmp(name, "arb_address"))
+		return snprintf(buf, PAGE_SIZE, "%04x\n", dci_obj->reg_addr);
+
+	if (!strcmp(name, "arb_value"))
+		reg_addr = dci_obj->reg_addr;
+	else if (get_static_reg_addr(ro_regs, name, &reg_addr) &&
+		 get_static_reg_addr(rw_regs, name, &reg_addr))
+		return -EFAULT;
+
+	err = drci_rd_reg(dci_obj->usb_device, reg_addr, &val);
+	if (err < 0)
+		return err;
+
+	return snprintf(buf, PAGE_SIZE, "%04x\n", val);
+}
+
+static ssize_t store_value(struct most_dci_obj *dci_obj,
+			   struct most_dci_attribute *attr,
+			   const char *buf, size_t count)
+{
+	u16 val;
+	u16 reg_addr;
+	const char *name = attr->attr.name;
+	struct usb_device *usb_dev = dci_obj->usb_device;
+	int err = kstrtou16(buf, 16, &val);
+
+	if (err)
+		return err;
+
+	if (!strcmp(name, "arb_address")) {
+		dci_obj->reg_addr = val;
+		return count;
+	}
+
+	if (!strcmp(name, "arb_value"))
+		err = drci_wr_reg(usb_dev, dci_obj->reg_addr, val);
+	else if (!strcmp(name, "sync_ep"))
+		err = start_sync_ep(usb_dev, val);
+	else if (!get_static_reg_addr(rw_regs, name, &reg_addr))
+		err = drci_wr_reg(usb_dev, reg_addr, val);
+	else
+		return -EFAULT;
+
+	if (err < 0)
+		return err;
+
+	return count;
+}
+
+static MOST_DCI_RO_ATTR(ni_state);
+static MOST_DCI_RO_ATTR(packet_bandwidth);
+static MOST_DCI_RO_ATTR(node_address);
+static MOST_DCI_RO_ATTR(node_position);
+static MOST_DCI_WO_ATTR(sync_ep);
+static MOST_DCI_ATTR(mep_filter);
+static MOST_DCI_ATTR(mep_hash0);
+static MOST_DCI_ATTR(mep_hash1);
+static MOST_DCI_ATTR(mep_hash2);
+static MOST_DCI_ATTR(mep_hash3);
+static MOST_DCI_ATTR(mep_eui48_hi);
+static MOST_DCI_ATTR(mep_eui48_mi);
+static MOST_DCI_ATTR(mep_eui48_lo);
+static MOST_DCI_ATTR(arb_address);
+static MOST_DCI_ATTR(arb_value);
+
+/**
+ * most_dci_def_attrs - array of default attribute files of the dci object
+ */
+static struct attribute *most_dci_def_attrs[] = {
+	&most_dci_attr_ni_state.attr,
+	&most_dci_attr_packet_bandwidth.attr,
+	&most_dci_attr_node_address.attr,
+	&most_dci_attr_node_position.attr,
+	&most_dci_attr_sync_ep.attr,
+	&most_dci_attr_mep_filter.attr,
+	&most_dci_attr_mep_hash0.attr,
+	&most_dci_attr_mep_hash1.attr,
+	&most_dci_attr_mep_hash2.attr,
+	&most_dci_attr_mep_hash3.attr,
+	&most_dci_attr_mep_eui48_hi.attr,
+	&most_dci_attr_mep_eui48_mi.attr,
+	&most_dci_attr_mep_eui48_lo.attr,
+	&most_dci_attr_arb_address.attr,
+	&most_dci_attr_arb_value.attr,
+	NULL,
+};
+
+/**
+ * DCI ktype
+ */
+static struct kobj_type most_dci_ktype = {
+	.sysfs_ops = &most_dci_sysfs_ops,
+	.release = most_dci_release,
+	.default_attrs = most_dci_def_attrs,
+};
+
+/**
+ * create_most_dci_obj - allocates a dci object
+ * @parent: parent kobject
+ *
+ * This creates a dci object and registers it with sysfs.
+ * Returns a pointer to the object or NULL when something went wrong.
+ */
+static struct
+most_dci_obj *create_most_dci_obj(struct kobject *parent)
+{
+	struct most_dci_obj *most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL);
+	int retval;
+
+	if (!most_dci)
+		return NULL;
+
+	retval = kobject_init_and_add(&most_dci->kobj, &most_dci_ktype, parent,
+				      "dci");
+	if (retval) {
+		kobject_put(&most_dci->kobj);
+		return NULL;
+	}
+	return most_dci;
+}
+
+/**
+ * destroy_most_dci_obj - DCI object release function
+ * @p: pointer to dci object
+ */
+static void destroy_most_dci_obj(struct most_dci_obj *p)
+{
+	kobject_put(&p->kobj);
+}
+
+/**
+ * hdm_probe - probe function of USB device driver
+ * @interface: Interface of the attached USB device
+ * @id: Pointer to the USB ID table.
+ *
+ * This allocates and initializes the device instance, adds the new
+ * entry to the internal list, scans the USB descriptors and registers
+ * the interface with the core.
+ * Additionally, the DCI objects are created and the hardware is sync'd.
+ *
+ * Return 0 on success. In case of an error a negative number is returned.
+ */
+static int
+hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+	struct usb_host_interface *usb_iface_desc = interface->cur_altsetting;
+	struct usb_device *usb_dev = interface_to_usbdev(interface);
+	struct device *dev = &usb_dev->dev;
+	struct most_dev *mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+	unsigned int i;
+	unsigned int num_endpoints;
+	struct most_channel_capability *tmp_cap;
+	struct usb_endpoint_descriptor *ep_desc;
+	int ret = 0;
+
+	if (!mdev)
+		goto exit_ENOMEM;
+
+	usb_set_intfdata(interface, mdev);
+	num_endpoints = usb_iface_desc->desc.bNumEndpoints;
+	mutex_init(&mdev->io_mutex);
+	INIT_WORK(&mdev->poll_work_obj, wq_netinfo);
+	setup_timer(&mdev->link_stat_timer, link_stat_timer_handler,
+		    (unsigned long)mdev);
+
+	mdev->usb_device = usb_dev;
+	mdev->link_stat_timer.expires = jiffies + (2 * HZ);
+
+	mdev->iface.mod = hdm_usb_fops.owner;
+	mdev->iface.interface = ITYPE_USB;
+	mdev->iface.configure = hdm_configure_channel;
+	mdev->iface.request_netinfo = hdm_request_netinfo;
+	mdev->iface.enqueue = hdm_enqueue;
+	mdev->iface.poison_channel = hdm_poison_channel;
+	mdev->iface.description = mdev->description;
+	mdev->iface.num_channels = num_endpoints;
+
+	snprintf(mdev->description, sizeof(mdev->description),
+		 "usb_device %d-%s:%d.%d",
+		 usb_dev->bus->busnum,
+		 usb_dev->devpath,
+		 usb_dev->config->desc.bConfigurationValue,
+		 usb_iface_desc->desc.bInterfaceNumber);
+
+	mdev->conf = kcalloc(num_endpoints, sizeof(*mdev->conf), GFP_KERNEL);
+	if (!mdev->conf)
+		goto exit_free;
+
+	mdev->cap = kcalloc(num_endpoints, sizeof(*mdev->cap), GFP_KERNEL);
+	if (!mdev->cap)
+		goto exit_free1;
+
+	mdev->iface.channel_vector = mdev->cap;
+	mdev->iface.priv = NULL;
+
+	mdev->ep_address =
+		kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL);
+	if (!mdev->ep_address)
+		goto exit_free2;
+
+	mdev->busy_urbs =
+		kcalloc(num_endpoints, sizeof(*mdev->busy_urbs), GFP_KERNEL);
+	if (!mdev->busy_urbs)
+		goto exit_free3;
+
+	tmp_cap = mdev->cap;
+	for (i = 0; i < num_endpoints; i++) {
+		ep_desc = &usb_iface_desc->endpoint[i].desc;
+		mdev->ep_address[i] = ep_desc->bEndpointAddress;
+		mdev->padding_active[i] = false;
+		mdev->is_channel_healthy[i] = true;
+
+		snprintf(&mdev->suffix[i][0], MAX_SUFFIX_LEN, "ep%02x",
+			 mdev->ep_address[i]);
+
+		tmp_cap->name_suffix = &mdev->suffix[i][0];
+		tmp_cap->buffer_size_packet = MAX_BUF_SIZE;
+		tmp_cap->buffer_size_streaming = MAX_BUF_SIZE;
+		tmp_cap->num_buffers_packet = BUF_CHAIN_SIZE;
+		tmp_cap->num_buffers_streaming = BUF_CHAIN_SIZE;
+		tmp_cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
+				     MOST_CH_ISOC | MOST_CH_SYNC;
+		if (usb_endpoint_dir_in(ep_desc))
+			tmp_cap->direction = MOST_CH_RX;
+		else
+			tmp_cap->direction = MOST_CH_TX;
+		tmp_cap++;
+		init_usb_anchor(&mdev->busy_urbs[i]);
+		spin_lock_init(&mdev->channel_lock[i]);
+	}
+	dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n",
+		   le16_to_cpu(usb_dev->descriptor.idVendor),
+		   le16_to_cpu(usb_dev->descriptor.idProduct),
+		   usb_dev->bus->busnum,
+		   usb_dev->devnum);
+
+	dev_notice(dev, "device path: /sys/bus/usb/devices/%d-%s:%d.%d\n",
+		   usb_dev->bus->busnum,
+		   usb_dev->devpath,
+		   usb_dev->config->desc.bConfigurationValue,
+		   usb_iface_desc->desc.bInterfaceNumber);
+
+	mdev->parent = most_register_interface(&mdev->iface);
+	if (IS_ERR(mdev->parent)) {
+		ret = PTR_ERR(mdev->parent);
+		goto exit_free4;
+	}
+
+	mutex_lock(&mdev->io_mutex);
+	if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 ||
+	    le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 ||
+	    le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) {
+		/* this increments the reference count of the instance
+		 * object of the core
+		 */
+		mdev->dci = create_most_dci_obj(mdev->parent);
+		if (!mdev->dci) {
+			mutex_unlock(&mdev->io_mutex);
+			most_deregister_interface(&mdev->iface);
+			ret = -ENOMEM;
+			goto exit_free4;
+		}
+
+		kobject_uevent(&mdev->dci->kobj, KOBJ_ADD);
+		mdev->dci->usb_device = mdev->usb_device;
+	}
+	mutex_unlock(&mdev->io_mutex);
+	return 0;
+
+exit_free4:
+	kfree(mdev->busy_urbs);
+exit_free3:
+	kfree(mdev->ep_address);
+exit_free2:
+	kfree(mdev->cap);
+exit_free1:
+	kfree(mdev->conf);
+exit_free:
+	kfree(mdev);
+exit_ENOMEM:
+	if (ret == 0 || ret == -ENOMEM) {
+		ret = -ENOMEM;
+		dev_err(dev, "out of memory\n");
+	}
+	return ret;
+}
+
+/**
+ * hdm_disconnect - disconnect function of USB device driver
+ * @interface: Interface of the attached USB device
+ *
+ * This deregisters the interface with the core, removes the kernel timer
+ * and frees resources.
+ *
+ * Context: hub kernel thread
+ */
+static void hdm_disconnect(struct usb_interface *interface)
+{
+	struct most_dev *mdev = usb_get_intfdata(interface);
+
+	mutex_lock(&mdev->io_mutex);
+	usb_set_intfdata(interface, NULL);
+	mdev->usb_device = NULL;
+	mutex_unlock(&mdev->io_mutex);
+
+	del_timer_sync(&mdev->link_stat_timer);
+	cancel_work_sync(&mdev->poll_work_obj);
+
+	destroy_most_dci_obj(mdev->dci);
+	most_deregister_interface(&mdev->iface);
+
+	kfree(mdev->busy_urbs);
+	kfree(mdev->cap);
+	kfree(mdev->conf);
+	kfree(mdev->ep_address);
+	kfree(mdev);
+}
+
+static struct usb_driver hdm_usb = {
+	.name = "hdm_usb",
+	.id_table = usbid,
+	.probe = hdm_probe,
+	.disconnect = hdm_disconnect,
+};
+
+module_usb_driver(hdm_usb);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_DESCRIPTION("HDM_4_USB");
diff --git a/drivers/staging/most/video/Kconfig b/drivers/staging/most/video/Kconfig
new file mode 100644
index 0000000..ce6af4f
--- /dev/null
+++ b/drivers/staging/most/video/Kconfig
@@ -0,0 +1,12 @@
+#
+# MOST V4L2 configuration
+#
+
+config MOST_VIDEO
+	tristate "Video"
+	depends on VIDEO_V4L2
+	---help---
+	  Say Y here if you want to commumicate via Video 4 Linux.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called most_video.
diff --git a/drivers/staging/most/video/Makefile b/drivers/staging/most/video/Makefile
new file mode 100644
index 0000000..1c8e520
--- /dev/null
+++ b/drivers/staging/most/video/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MOST_VIDEO) += most_video.o
+
+most_video-objs := video.o
+ccflags-y += -Idrivers/staging/
diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c
new file mode 100644
index 0000000..eed9046
--- /dev/null
+++ b/drivers/staging/most/video/video.c
@@ -0,0 +1,616 @@
+/*
+ * V4L2 AIM - V4L2 Application Interface Module for MostCore
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/videodev2.h>
+#include <linux/mutex.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+
+#include <most/core.h>
+
+#define V4L2_AIM_MAX_INPUT  1
+
+static struct most_aim aim_info;
+
+struct most_video_dev {
+	struct most_interface *iface;
+	int ch_idx;
+	struct list_head list;
+	bool mute;
+
+	struct list_head pending_mbos;
+	spinlock_t list_lock;
+
+	struct v4l2_device v4l2_dev;
+	atomic_t access_ref;
+	struct video_device *vdev;
+	unsigned int ctrl_input;
+
+	struct mutex lock;
+
+	wait_queue_head_t wait_data;
+};
+
+struct aim_fh {
+	/* must be the first field of this struct! */
+	struct v4l2_fh fh;
+	struct most_video_dev *mdev;
+	u32 offs;
+};
+
+static struct list_head video_devices = LIST_HEAD_INIT(video_devices);
+static struct spinlock list_lock;
+
+static inline bool data_ready(struct most_video_dev *mdev)
+{
+	return !list_empty(&mdev->pending_mbos);
+}
+
+static inline struct mbo *get_top_mbo(struct most_video_dev *mdev)
+{
+	return list_first_entry(&mdev->pending_mbos, struct mbo, list);
+}
+
+static int aim_vdev_open(struct file *filp)
+{
+	int ret;
+	struct video_device *vdev = video_devdata(filp);
+	struct most_video_dev *mdev = video_drvdata(filp);
+	struct aim_fh *fh;
+
+	v4l2_info(&mdev->v4l2_dev, "aim_vdev_open()\n");
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+	if (!fh)
+		return -ENOMEM;
+
+	if (!atomic_inc_and_test(&mdev->access_ref)) {
+		v4l2_err(&mdev->v4l2_dev, "too many clients\n");
+		ret = -EBUSY;
+		goto err_dec;
+	}
+
+	fh->mdev = mdev;
+	v4l2_fh_init(&fh->fh, vdev);
+	filp->private_data = fh;
+
+	v4l2_fh_add(&fh->fh);
+
+	ret = most_start_channel(mdev->iface, mdev->ch_idx, &aim_info);
+	if (ret) {
+		v4l2_err(&mdev->v4l2_dev, "most_start_channel() failed\n");
+		goto err_rm;
+	}
+
+	return 0;
+
+err_rm:
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
+
+err_dec:
+	atomic_dec(&mdev->access_ref);
+	kfree(fh);
+	return ret;
+}
+
+static int aim_vdev_close(struct file *filp)
+{
+	struct aim_fh *fh = filp->private_data;
+	struct most_video_dev *mdev = fh->mdev;
+	struct mbo *mbo, *tmp;
+
+	v4l2_info(&mdev->v4l2_dev, "aim_vdev_close()\n");
+
+	/*
+	 * We need to put MBOs back before we call most_stop_channel()
+	 * to deallocate MBOs.
+	 * From the other hand mostcore still calling rx_completion()
+	 * to deliver MBOs until most_stop_channel() is called.
+	 * Use mute to work around this issue.
+	 * This must be implemented in core.
+	 */
+
+	spin_lock_irq(&mdev->list_lock);
+	mdev->mute = true;
+	list_for_each_entry_safe(mbo, tmp, &mdev->pending_mbos, list) {
+		list_del(&mbo->list);
+		spin_unlock_irq(&mdev->list_lock);
+		most_put_mbo(mbo);
+		spin_lock_irq(&mdev->list_lock);
+	}
+	spin_unlock_irq(&mdev->list_lock);
+	most_stop_channel(mdev->iface, mdev->ch_idx, &aim_info);
+	mdev->mute = false;
+
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
+
+	atomic_dec(&mdev->access_ref);
+	kfree(fh);
+	return 0;
+}
+
+static ssize_t aim_vdev_read(struct file *filp, char __user *buf,
+			     size_t count, loff_t *pos)
+{
+	struct aim_fh *fh = filp->private_data;
+	struct most_video_dev *mdev = fh->mdev;
+	int ret = 0;
+
+	if (*pos)
+		return -ESPIPE;
+
+	if (!mdev)
+		return -ENODEV;
+
+	/* wait for the first buffer */
+	if (!(filp->f_flags & O_NONBLOCK)) {
+		if (wait_event_interruptible(mdev->wait_data, data_ready(mdev)))
+			return -ERESTARTSYS;
+	}
+
+	if (!data_ready(mdev))
+		return -EAGAIN;
+
+	while (count > 0 && data_ready(mdev)) {
+		struct mbo *const mbo = get_top_mbo(mdev);
+		int const rem = mbo->processed_length - fh->offs;
+		int const cnt = rem < count ? rem : count;
+
+		if (copy_to_user(buf, mbo->virt_address + fh->offs, cnt)) {
+			v4l2_err(&mdev->v4l2_dev, "read: copy_to_user failed\n");
+			if (!ret)
+				ret = -EFAULT;
+			return ret;
+		}
+
+		fh->offs += cnt;
+		count -= cnt;
+		buf += cnt;
+		ret += cnt;
+
+		if (cnt >= rem) {
+			fh->offs = 0;
+			spin_lock_irq(&mdev->list_lock);
+			list_del(&mbo->list);
+			spin_unlock_irq(&mdev->list_lock);
+			most_put_mbo(mbo);
+		}
+	}
+	return ret;
+}
+
+static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait)
+{
+	struct aim_fh *fh = filp->private_data;
+	struct most_video_dev *mdev = fh->mdev;
+	unsigned int mask = 0;
+
+	/* only wait if no data is available */
+	if (!data_ready(mdev))
+		poll_wait(filp, &mdev->wait_data, wait);
+	if (data_ready(mdev))
+		mask |= POLLIN | POLLRDNORM;
+
+	return mask;
+}
+
+static void aim_set_format_struct(struct v4l2_format *f)
+{
+	f->fmt.pix.width = 8;
+	f->fmt.pix.height = 8;
+	f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
+	f->fmt.pix.bytesperline = 0;
+	f->fmt.pix.sizeimage = 188 * 2;
+	f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+	f->fmt.pix.field = V4L2_FIELD_NONE;
+	f->fmt.pix.priv = 0;
+}
+
+static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd,
+			  struct v4l2_format *format)
+{
+	if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG)
+		return -EINVAL;
+
+	if (cmd == VIDIOC_TRY_FMT)
+		return 0;
+
+	aim_set_format_struct(format);
+
+	return 0;
+}
+
+static int vidioc_querycap(struct file *file, void *priv,
+			   struct v4l2_capability *cap)
+{
+	struct aim_fh *fh = priv;
+	struct most_video_dev *mdev = fh->mdev;
+
+	v4l2_info(&mdev->v4l2_dev, "vidioc_querycap()\n");
+
+	strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver));
+	strlcpy(cap->card, "MOST", sizeof(cap->card));
+	snprintf(cap->bus_info, sizeof(cap->bus_info),
+		 "%s", mdev->iface->description);
+
+	cap->capabilities =
+		V4L2_CAP_READWRITE |
+		V4L2_CAP_TUNER |
+		V4L2_CAP_VIDEO_CAPTURE;
+	return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+				   struct v4l2_fmtdesc *f)
+{
+	struct aim_fh *fh = priv;
+	struct most_video_dev *mdev = fh->mdev;
+
+	v4l2_info(&mdev->v4l2_dev, "vidioc_enum_fmt_vid_cap() %d\n", f->index);
+
+	if (f->index)
+		return -EINVAL;
+
+	strcpy(f->description, "MPEG");
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	f->flags = V4L2_FMT_FLAG_COMPRESSED;
+	f->pixelformat = V4L2_PIX_FMT_MPEG;
+
+	return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct aim_fh *fh = priv;
+	struct most_video_dev *mdev = fh->mdev;
+
+	v4l2_info(&mdev->v4l2_dev, "vidioc_g_fmt_vid_cap()\n");
+
+	aim_set_format_struct(f);
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+				  struct v4l2_format *f)
+{
+	struct aim_fh *fh = priv;
+	struct most_video_dev *mdev = fh->mdev;
+
+	return aim_set_format(mdev, VIDIOC_TRY_FMT, f);
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct aim_fh *fh = priv;
+	struct most_video_dev *mdev = fh->mdev;
+
+	return aim_set_format(mdev, VIDIOC_S_FMT, f);
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+	struct aim_fh *fh = priv;
+	struct most_video_dev *mdev = fh->mdev;
+
+	v4l2_info(&mdev->v4l2_dev, "vidioc_g_std()\n");
+
+	*norm = V4L2_STD_UNKNOWN;
+	return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+			     struct v4l2_input *input)
+{
+	struct aim_fh *fh = priv;
+	struct most_video_dev *mdev = fh->mdev;
+
+	if (input->index >= V4L2_AIM_MAX_INPUT)
+		return -EINVAL;
+
+	strcpy(input->name, "MOST Video");
+	input->type |= V4L2_INPUT_TYPE_CAMERA;
+	input->audioset = 0;
+
+	input->std = mdev->vdev->tvnorms;
+
+	return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	struct aim_fh *fh = priv;
+	struct most_video_dev *mdev = fh->mdev;
+	*i = mdev->ctrl_input;
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
+{
+	struct aim_fh *fh = priv;
+	struct most_video_dev *mdev = fh->mdev;
+
+	v4l2_info(&mdev->v4l2_dev, "vidioc_s_input(%d)\n", index);
+
+	if (index >= V4L2_AIM_MAX_INPUT)
+		return -EINVAL;
+	mdev->ctrl_input = index;
+	return 0;
+}
+
+static const struct v4l2_file_operations aim_fops = {
+	.owner      = THIS_MODULE,
+	.open       = aim_vdev_open,
+	.release    = aim_vdev_close,
+	.read       = aim_vdev_read,
+	.poll       = aim_vdev_poll,
+	.unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+	.vidioc_querycap            = vidioc_querycap,
+	.vidioc_enum_fmt_vid_cap    = vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap       = vidioc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap     = vidioc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
+	.vidioc_g_std               = vidioc_g_std,
+	.vidioc_enum_input          = vidioc_enum_input,
+	.vidioc_g_input             = vidioc_g_input,
+	.vidioc_s_input             = vidioc_s_input,
+};
+
+static const struct video_device aim_videodev_template = {
+	.fops = &aim_fops,
+	.release = video_device_release,
+	.ioctl_ops = &video_ioctl_ops,
+	.tvnorms = V4L2_STD_UNKNOWN,
+};
+
+/**************************************************************************/
+
+static struct most_video_dev *get_aim_dev(
+	struct most_interface *iface, int channel_idx)
+{
+	struct most_video_dev *mdev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&list_lock, flags);
+	list_for_each_entry(mdev, &video_devices, list) {
+		if (mdev->iface == iface && mdev->ch_idx == channel_idx) {
+			spin_unlock_irqrestore(&list_lock, flags);
+			return mdev;
+		}
+	}
+	spin_unlock_irqrestore(&list_lock, flags);
+	return NULL;
+}
+
+static int aim_rx_data(struct mbo *mbo)
+{
+	unsigned long flags;
+	struct most_video_dev *mdev =
+		get_aim_dev(mbo->ifp, mbo->hdm_channel_id);
+
+	if (!mdev)
+		return -EIO;
+
+	spin_lock_irqsave(&mdev->list_lock, flags);
+	if (unlikely(mdev->mute)) {
+		spin_unlock_irqrestore(&mdev->list_lock, flags);
+		return -EIO;
+	}
+
+	list_add_tail(&mbo->list, &mdev->pending_mbos);
+	spin_unlock_irqrestore(&mdev->list_lock, flags);
+	wake_up_interruptible(&mdev->wait_data);
+	return 0;
+}
+
+static int aim_register_videodev(struct most_video_dev *mdev)
+{
+	int ret;
+
+	v4l2_info(&mdev->v4l2_dev, "aim_register_videodev()\n");
+
+	init_waitqueue_head(&mdev->wait_data);
+
+	/* allocate and fill v4l2 video struct */
+	mdev->vdev = video_device_alloc();
+	if (!mdev->vdev)
+		return -ENOMEM;
+
+	/* Fill the video capture device struct */
+	*mdev->vdev = aim_videodev_template;
+	mdev->vdev->v4l2_dev = &mdev->v4l2_dev;
+	mdev->vdev->lock = &mdev->lock;
+	snprintf(mdev->vdev->name, sizeof(mdev->vdev->name), "MOST: %s",
+		 mdev->v4l2_dev.name);
+
+	/* Register the v4l2 device */
+	video_set_drvdata(mdev->vdev, mdev);
+	ret = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1);
+	if (ret) {
+		v4l2_err(&mdev->v4l2_dev, "video_register_device failed (%d)\n",
+			 ret);
+		video_device_release(mdev->vdev);
+	}
+
+	return ret;
+}
+
+static void aim_unregister_videodev(struct most_video_dev *mdev)
+{
+	v4l2_info(&mdev->v4l2_dev, "aim_unregister_videodev()\n");
+
+	video_unregister_device(mdev->vdev);
+}
+
+static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev)
+{
+	struct most_video_dev *mdev =
+		container_of(v4l2_dev, struct most_video_dev, v4l2_dev);
+
+	v4l2_device_unregister(v4l2_dev);
+	kfree(mdev);
+}
+
+static int aim_probe_channel(struct most_interface *iface, int channel_idx,
+			     struct most_channel_config *ccfg,
+			     struct kobject *parent, char *name)
+{
+	int ret;
+	struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
+
+	pr_info("aim_probe_channel(%s)\n", name);
+
+	if (mdev) {
+		pr_err("channel already linked\n");
+		return -EEXIST;
+	}
+
+	if (ccfg->direction != MOST_CH_RX) {
+		pr_err("wrong direction, expect rx\n");
+		return -EINVAL;
+	}
+
+	if (ccfg->data_type != MOST_CH_SYNC &&
+	    ccfg->data_type != MOST_CH_ISOC) {
+		pr_err("wrong channel type, expect sync or isoc\n");
+		return -EINVAL;
+	}
+
+	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+	if (!mdev)
+		return -ENOMEM;
+
+	mutex_init(&mdev->lock);
+	atomic_set(&mdev->access_ref, -1);
+	spin_lock_init(&mdev->list_lock);
+	INIT_LIST_HEAD(&mdev->pending_mbos);
+	mdev->iface = iface;
+	mdev->ch_idx = channel_idx;
+	mdev->v4l2_dev.release = aim_v4l2_dev_release;
+
+	/* Create the v4l2_device */
+	strlcpy(mdev->v4l2_dev.name, name, sizeof(mdev->v4l2_dev.name));
+	ret = v4l2_device_register(NULL, &mdev->v4l2_dev);
+	if (ret) {
+		pr_err("v4l2_device_register() failed\n");
+		kfree(mdev);
+		return ret;
+	}
+
+	ret = aim_register_videodev(mdev);
+	if (ret)
+		goto err_unreg;
+
+	spin_lock_irq(&list_lock);
+	list_add(&mdev->list, &video_devices);
+	spin_unlock_irq(&list_lock);
+	v4l2_info(&mdev->v4l2_dev, "aim_probe_channel() done\n");
+	return 0;
+
+err_unreg:
+	v4l2_device_disconnect(&mdev->v4l2_dev);
+	v4l2_device_put(&mdev->v4l2_dev);
+	return ret;
+}
+
+static int aim_disconnect_channel(struct most_interface *iface,
+				  int channel_idx)
+{
+	struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
+
+	if (!mdev) {
+		pr_err("no such channel is linked\n");
+		return -ENOENT;
+	}
+
+	v4l2_info(&mdev->v4l2_dev, "aim_disconnect_channel()\n");
+
+	spin_lock_irq(&list_lock);
+	list_del(&mdev->list);
+	spin_unlock_irq(&list_lock);
+
+	aim_unregister_videodev(mdev);
+	v4l2_device_disconnect(&mdev->v4l2_dev);
+	v4l2_device_put(&mdev->v4l2_dev);
+	return 0;
+}
+
+static struct most_aim aim_info = {
+	.name = "v4l",
+	.probe_channel = aim_probe_channel,
+	.disconnect_channel = aim_disconnect_channel,
+	.rx_completion = aim_rx_data,
+};
+
+static int __init aim_init(void)
+{
+	spin_lock_init(&list_lock);
+	return most_register_aim(&aim_info);
+}
+
+static void __exit aim_exit(void)
+{
+	struct most_video_dev *mdev, *tmp;
+
+	/*
+	 * As the mostcore currently doesn't call disconnect_channel()
+	 * for linked channels while we call most_deregister_aim()
+	 * we simulate this call here.
+	 * This must be fixed in core.
+	 */
+	spin_lock_irq(&list_lock);
+	list_for_each_entry_safe(mdev, tmp, &video_devices, list) {
+		list_del(&mdev->list);
+		spin_unlock_irq(&list_lock);
+
+		aim_unregister_videodev(mdev);
+		v4l2_device_disconnect(&mdev->v4l2_dev);
+		v4l2_device_put(&mdev->v4l2_dev);
+		spin_lock_irq(&list_lock);
+	}
+	spin_unlock_irq(&list_lock);
+
+	most_deregister_aim(&aim_info);
+	BUG_ON(!list_empty(&video_devices));
+}
+
+module_init(aim_init);
+module_exit(aim_exit);
+
+MODULE_DESCRIPTION("V4L2 Application Interface Module for MostCore");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_LICENSE("GPL");
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 02/26] staging: most: integrate driver in kernel's device model
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 03/26] staging: most: core: rename structure Christian Gromm
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

The following patch adapts the driver to use the device model by:

	- adopting the MOST bus_type
	- registering the core as a busdriver
	- removing private kobject/kset usage
	- removing private lists and structures to track registered modules
	  and making use of the device model API
	- removing prefix of modules
	- allowing adapter drivers (a.k.a. HDM) to register MOST devices
	- registering AIM modules as components with the core to build
	  the user space experience of the driver stack
	- using attribute groups to create the sysfs files
	- renaming variables to prevent collision with the introduced device
	  structs.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/cdev/cdev.c   |   6 +-
 drivers/staging/most/core.c        | 930 ++++++++++++-------------------------
 drivers/staging/most/core.h        |   9 +-
 drivers/staging/most/dim2/dim2.c   |  20 +-
 drivers/staging/most/dim2/sysfs.c  |  92 +---
 drivers/staging/most/dim2/sysfs.h  |   6 +-
 drivers/staging/most/i2c/i2c.c     |   7 +-
 drivers/staging/most/net/net.c     |   4 +-
 drivers/staging/most/sound/sound.c |   5 +-
 drivers/staging/most/usb/usb.c     | 244 +++-------
 drivers/staging/most/video/video.c |   4 +-
 11 files changed, 405 insertions(+), 922 deletions(-)

diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c
index 3dce5e0..4b4c112 100644
--- a/drivers/staging/most/cdev/cdev.c
+++ b/drivers/staging/most/cdev/cdev.c
@@ -427,14 +427,14 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id)
  */
 static int aim_probe(struct most_interface *iface, int channel_id,
 		     struct most_channel_config *cfg,
-		     struct kobject *parent, char *name)
+		     char *name)
 {
 	struct aim_channel *c;
 	unsigned long cl_flags;
 	int retval;
 	int current_minor;
 
-	if ((!iface) || (!cfg) || (!parent) || (!name)) {
+	if ((!iface) || (!cfg) || (!name)) {
 		pr_info("Probing AIM with bad arguments");
 		return -EINVAL;
 	}
@@ -498,7 +498,7 @@ static int aim_probe(struct most_interface *iface, int channel_id,
 }
 
 static struct most_aim cdev_aim = {
-	.name = "cdev",
+	.name = "aim_cdev",
 	.probe_channel = aim_probe,
 	.disconnect_channel = aim_disconnect_channel,
 	.rx_completion = aim_rx_completion,
diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 6ee6acf..54a56a0 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -33,7 +33,7 @@
 #define STRING_SIZE	80
 
 static struct class *most_class;
-static struct device *core_dev;
+static struct device core_dev;
 static struct ida mdev_id;
 static int dummy_num_buffers;
 
@@ -44,7 +44,7 @@ struct most_c_aim_obj {
 };
 
 struct most_c_obj {
-	struct kobject kobj;
+	struct device dev;
 	struct completion cleanup;
 	atomic_t mbo_ref;
 	atomic_t mbo_nq_level;
@@ -69,14 +69,13 @@ struct most_c_obj {
 	wait_queue_head_t hdm_fifo_wq;
 };
 
-#define to_c_obj(d) container_of(d, struct most_c_obj, kobj)
+#define to_c_obj(d) container_of(d, struct most_c_obj, dev)
 
 struct most_inst_obj {
 	int dev_id;
 	struct most_interface *iface;
 	struct list_head channel_list;
 	struct most_c_obj *channel[MAX_CHANNELS];
-	struct kobject kobj;
 	struct list_head list;
 };
 
@@ -91,8 +90,23 @@ struct most_inst_obj {
 	{ MOST_CH_ISOC, "isoc_avp\n"},
 };
 
-#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj)
+int most_match(struct device *dev, struct device_driver *drv)
+{
+	if (!strcmp(dev_name(dev), "most"))
+		return 0;
+	else
+		return 1;
+}
+
+static struct bus_type most_bus_type = {
+	.name = "most",
+	.match = most_match,
+};
 
+static struct device_driver mostcore = {
+	.name = "most_core",
+	.bus = &most_bus_type,
+};
 /**
  * list_pop_mbo - retrieves the first MBO of the list and removes it
  * @ptr: the list head to grab the MBO from.
@@ -108,67 +122,6 @@ struct most_inst_obj {
  *		     ___C H A N N E L___
  */
 
-/**
- * struct most_c_attr - to access the attributes of a channel object
- * @attr: attributes of a channel
- * @show: pointer to the show function
- * @store: pointer to the store function
- */
-struct most_c_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct most_c_obj *d,
-			struct most_c_attr *attr,
-			char *buf);
-	ssize_t (*store)(struct most_c_obj *d,
-			 struct most_c_attr *attr,
-			 const char *buf,
-			 size_t count);
-};
-
-#define to_channel_attr(a) container_of(a, struct most_c_attr, attr)
-
-/**
- * channel_attr_show - show function of channel object
- * @kobj: pointer to its kobject
- * @attr: pointer to its attributes
- * @buf: buffer
- */
-static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr,
-				 char *buf)
-{
-	struct most_c_attr *channel_attr = to_channel_attr(attr);
-	struct most_c_obj *c_obj = to_c_obj(kobj);
-
-	if (!channel_attr->show)
-		return -EIO;
-
-	return channel_attr->show(c_obj, channel_attr, buf);
-}
-
-/**
- * channel_attr_store - store function of channel object
- * @kobj: pointer to its kobject
- * @attr: pointer to its attributes
- * @buf: buffer
- * @len: length of buffer
- */
-static ssize_t channel_attr_store(struct kobject *kobj,
-				  struct attribute *attr,
-				  const char *buf,
-				  size_t len)
-{
-	struct most_c_attr *channel_attr = to_channel_attr(attr);
-	struct most_c_obj *c_obj = to_c_obj(kobj);
-
-	if (!channel_attr->store)
-		return -EIO;
-	return channel_attr->store(c_obj, channel_attr, buf, len);
-}
-
-static const struct sysfs_ops most_channel_sysfs_ops = {
-	.show = channel_attr_show,
-	.store = channel_attr_store,
-};
 
 /**
  * most_free_mbo_coherent - free an MBO and its coherent buffer
@@ -241,21 +194,11 @@ static int flush_trash_fifo(struct most_c_obj *c)
 	return 0;
 }
 
-/**
- * most_channel_release - release function of channel object
- * @kobj: pointer to channel's kobject
- */
-static void most_channel_release(struct kobject *kobj)
-{
-	struct most_c_obj *c = to_c_obj(kobj);
-
-	kfree(c);
-}
-
-static ssize_t available_directions_show(struct most_c_obj *c,
-					 struct most_c_attr *attr,
+static ssize_t available_directions_show(struct device *dev,
+					 struct device_attribute *attr,
 					 char *buf)
 {
+	struct most_c_obj *c = to_c_obj(dev);
 	unsigned int i = c->channel_id;
 
 	strcpy(buf, "");
@@ -267,10 +210,11 @@ static ssize_t available_directions_show(struct most_c_obj *c,
 	return strlen(buf);
 }
 
-static ssize_t available_datatypes_show(struct most_c_obj *c,
-					struct most_c_attr *attr,
+static ssize_t available_datatypes_show(struct device *dev,
+					struct device_attribute *attr,
 					char *buf)
 {
+	struct most_c_obj *c = to_c_obj(dev);
 	unsigned int i = c->channel_id;
 
 	strcpy(buf, "");
@@ -286,65 +230,75 @@ static ssize_t available_datatypes_show(struct most_c_obj *c,
 	return strlen(buf);
 }
 
-static ssize_t number_of_packet_buffers_show(struct most_c_obj *c,
-					     struct most_c_attr *attr,
+static ssize_t number_of_packet_buffers_show(struct device *dev,
+					     struct device_attribute *attr,
 					     char *buf)
 {
+	struct most_c_obj *c = to_c_obj(dev);
 	unsigned int i = c->channel_id;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 			c->iface->channel_vector[i].num_buffers_packet);
 }
 
-static ssize_t number_of_stream_buffers_show(struct most_c_obj *c,
-					     struct most_c_attr *attr,
+static ssize_t number_of_stream_buffers_show(struct device *dev,
+					     struct device_attribute *attr,
 					     char *buf)
 {
+	struct most_c_obj *c = to_c_obj(dev);
 	unsigned int i = c->channel_id;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 			c->iface->channel_vector[i].num_buffers_streaming);
 }
 
-static ssize_t size_of_packet_buffer_show(struct most_c_obj *c,
-					  struct most_c_attr *attr,
+static ssize_t size_of_packet_buffer_show(struct device *dev,
+					  struct device_attribute *attr,
 					  char *buf)
 {
+	struct most_c_obj *c = to_c_obj(dev);
 	unsigned int i = c->channel_id;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 			c->iface->channel_vector[i].buffer_size_packet);
 }
 
-static ssize_t size_of_stream_buffer_show(struct most_c_obj *c,
-					  struct most_c_attr *attr,
+static ssize_t size_of_stream_buffer_show(struct device *dev,
+					  struct device_attribute *attr,
 					  char *buf)
 {
+	struct most_c_obj *c = to_c_obj(dev);
 	unsigned int i = c->channel_id;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 			c->iface->channel_vector[i].buffer_size_streaming);
 }
 
-static ssize_t channel_starving_show(struct most_c_obj *c,
-				     struct most_c_attr *attr,
+static ssize_t channel_starving_show(struct device *dev,
+				     struct device_attribute *attr,
 				     char *buf)
 {
+	struct most_c_obj *c = to_c_obj(dev);
+
 	return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving);
 }
 
-static ssize_t set_number_of_buffers_show(struct most_c_obj *c,
-					  struct most_c_attr *attr,
+static ssize_t set_number_of_buffers_show(struct device *dev,
+					  struct device_attribute *attr,
 					  char *buf)
 {
+	struct most_c_obj *c = to_c_obj(dev);
+
 	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers);
 }
 
-static ssize_t set_number_of_buffers_store(struct most_c_obj *c,
-					   struct most_c_attr *attr,
+static ssize_t set_number_of_buffers_store(struct device *dev,
+					   struct device_attribute *attr,
 					   const char *buf,
 					   size_t count)
 {
+	struct most_c_obj *c = to_c_obj(dev);
+
 	int ret = kstrtou16(buf, 0, &c->cfg.num_buffers);
 
 	if (ret)
@@ -352,18 +306,22 @@ static ssize_t set_number_of_buffers_store(struct most_c_obj *c,
 	return count;
 }
 
-static ssize_t set_buffer_size_show(struct most_c_obj *c,
-				    struct most_c_attr *attr,
+static ssize_t set_buffer_size_show(struct device *dev,
+				    struct device_attribute *attr,
 				    char *buf)
 {
+	struct most_c_obj *c = to_c_obj(dev);
+
 	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size);
 }
 
-static ssize_t set_buffer_size_store(struct most_c_obj *c,
-				     struct most_c_attr *attr,
+static ssize_t set_buffer_size_store(struct device *dev,
+				     struct device_attribute *attr,
 				     const char *buf,
 				     size_t count)
 {
+	struct most_c_obj *c = to_c_obj(dev);
+
 	int ret = kstrtou16(buf, 0, &c->cfg.buffer_size);
 
 	if (ret)
@@ -371,10 +329,12 @@ static ssize_t set_buffer_size_store(struct most_c_obj *c,
 	return count;
 }
 
-static ssize_t set_direction_show(struct most_c_obj *c,
-				  struct most_c_attr *attr,
+static ssize_t set_direction_show(struct device *dev,
+				  struct device_attribute *attr,
 				  char *buf)
 {
+	struct most_c_obj *c = to_c_obj(dev);
+
 	if (c->cfg.direction & MOST_CH_TX)
 		return snprintf(buf, PAGE_SIZE, "tx\n");
 	else if (c->cfg.direction & MOST_CH_RX)
@@ -382,11 +342,13 @@ static ssize_t set_direction_show(struct most_c_obj *c,
 	return snprintf(buf, PAGE_SIZE, "unconfigured\n");
 }
 
-static ssize_t set_direction_store(struct most_c_obj *c,
-				   struct most_c_attr *attr,
+static ssize_t set_direction_store(struct device *dev,
+				   struct device_attribute *attr,
 				   const char *buf,
 				   size_t count)
 {
+	struct most_c_obj *c = to_c_obj(dev);
+
 	if (!strcmp(buf, "dir_rx\n")) {
 		c->cfg.direction = MOST_CH_RX;
 	} else if (!strcmp(buf, "rx\n")) {
@@ -402,11 +364,12 @@ static ssize_t set_direction_store(struct most_c_obj *c,
 	return count;
 }
 
-static ssize_t set_datatype_show(struct most_c_obj *c,
-				 struct most_c_attr *attr,
+static ssize_t set_datatype_show(struct device *dev,
+				 struct device_attribute *attr,
 				 char *buf)
 {
 	int i;
+	struct most_c_obj *c = to_c_obj(dev);
 
 	for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
 		if (c->cfg.data_type & ch_data_type[i].most_ch_data_type)
@@ -415,12 +378,13 @@ static ssize_t set_datatype_show(struct most_c_obj *c,
 	return snprintf(buf, PAGE_SIZE, "unconfigured\n");
 }
 
-static ssize_t set_datatype_store(struct most_c_obj *c,
-				  struct most_c_attr *attr,
+static ssize_t set_datatype_store(struct device *dev,
+				  struct device_attribute *attr,
 				  const char *buf,
 				  size_t count)
 {
 	int i;
+	struct most_c_obj *c = to_c_obj(dev);
 
 	for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
 		if (!strcmp(buf, ch_data_type[i].name)) {
@@ -436,18 +400,22 @@ static ssize_t set_datatype_store(struct most_c_obj *c,
 	return count;
 }
 
-static ssize_t set_subbuffer_size_show(struct most_c_obj *c,
-				       struct most_c_attr *attr,
+static ssize_t set_subbuffer_size_show(struct device *dev,
+				       struct device_attribute *attr,
 				       char *buf)
 {
+	struct most_c_obj *c = to_c_obj(dev);
+
 	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size);
 }
 
-static ssize_t set_subbuffer_size_store(struct most_c_obj *c,
-					struct most_c_attr *attr,
+static ssize_t set_subbuffer_size_store(struct device *dev,
+					struct device_attribute *attr,
 					const char *buf,
 					size_t count)
 {
+	struct most_c_obj *c = to_c_obj(dev);
+
 	int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size);
 
 	if (ret)
@@ -455,18 +423,22 @@ static ssize_t set_subbuffer_size_store(struct most_c_obj *c,
 	return count;
 }
 
-static ssize_t set_packets_per_xact_show(struct most_c_obj *c,
-					 struct most_c_attr *attr,
+static ssize_t set_packets_per_xact_show(struct device *dev,
+					 struct device_attribute *attr,
 					 char *buf)
 {
+	struct most_c_obj *c = to_c_obj(dev);
+
 	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact);
 }
 
-static ssize_t set_packets_per_xact_store(struct most_c_obj *c,
-					  struct most_c_attr *attr,
+static ssize_t set_packets_per_xact_store(struct device *dev,
+					  struct device_attribute *attr,
 					  const char *buf,
 					  size_t count)
 {
+	struct most_c_obj *c = to_c_obj(dev);
+
 	int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact);
 
 	if (ret)
@@ -474,77 +446,47 @@ static ssize_t set_packets_per_xact_store(struct most_c_obj *c,
 	return count;
 }
 
-static struct most_c_attr most_c_attrs[] = {
-	__ATTR_RO(available_directions),
-	__ATTR_RO(available_datatypes),
-	__ATTR_RO(number_of_packet_buffers),
-	__ATTR_RO(number_of_stream_buffers),
-	__ATTR_RO(size_of_stream_buffer),
-	__ATTR_RO(size_of_packet_buffer),
-	__ATTR_RO(channel_starving),
-	__ATTR_RW(set_buffer_size),
-	__ATTR_RW(set_number_of_buffers),
-	__ATTR_RW(set_direction),
-	__ATTR_RW(set_datatype),
-	__ATTR_RW(set_subbuffer_size),
-	__ATTR_RW(set_packets_per_xact),
-};
-
-/**
- * most_channel_def_attrs - array of default attributes of channel object
- */
-static struct attribute *most_channel_def_attrs[] = {
-	&most_c_attrs[0].attr,
-	&most_c_attrs[1].attr,
-	&most_c_attrs[2].attr,
-	&most_c_attrs[3].attr,
-	&most_c_attrs[4].attr,
-	&most_c_attrs[5].attr,
-	&most_c_attrs[6].attr,
-	&most_c_attrs[7].attr,
-	&most_c_attrs[8].attr,
-	&most_c_attrs[9].attr,
-	&most_c_attrs[10].attr,
-	&most_c_attrs[11].attr,
-	&most_c_attrs[12].attr,
+#define DEV_ATTR(_name)  &dev_attr_##_name.attr
+
+static DEVICE_ATTR_RO(available_directions);
+static DEVICE_ATTR_RO(available_datatypes);
+static DEVICE_ATTR_RO(number_of_packet_buffers);
+static DEVICE_ATTR_RO(number_of_stream_buffers);
+static DEVICE_ATTR_RO(size_of_stream_buffer);
+static DEVICE_ATTR_RO(size_of_packet_buffer);
+static DEVICE_ATTR_RO(channel_starving);
+static DEVICE_ATTR_RW(set_buffer_size);
+static DEVICE_ATTR_RW(set_number_of_buffers);
+static DEVICE_ATTR_RW(set_direction);
+static DEVICE_ATTR_RW(set_datatype);
+static DEVICE_ATTR_RW(set_subbuffer_size);
+static DEVICE_ATTR_RW(set_packets_per_xact);
+
+static struct attribute *channel_attrs[] = {
+	DEV_ATTR(available_directions),
+	DEV_ATTR(available_datatypes),
+	DEV_ATTR(number_of_packet_buffers),
+	DEV_ATTR(number_of_stream_buffers),
+	DEV_ATTR(size_of_stream_buffer),
+	DEV_ATTR(size_of_packet_buffer),
+	DEV_ATTR(channel_starving),
+	DEV_ATTR(set_buffer_size),
+	DEV_ATTR(set_number_of_buffers),
+	DEV_ATTR(set_direction),
+	DEV_ATTR(set_datatype),
+	DEV_ATTR(set_subbuffer_size),
+	DEV_ATTR(set_packets_per_xact),
 	NULL,
 };
 
-static struct kobj_type most_channel_ktype = {
-	.sysfs_ops = &most_channel_sysfs_ops,
-	.release = most_channel_release,
-	.default_attrs = most_channel_def_attrs,
+static struct attribute_group channel_attr_group = {
+	.attrs = channel_attrs,
 };
 
-static struct kset *most_channel_kset;
-
-/**
- * create_most_c_obj - allocates a channel object
- * @name: name of the channel object
- * @parent: parent kobject
- *
- * This create a channel object and registers it with sysfs.
- * Returns a pointer to the object or NULL when something went wrong.
- */
-static struct most_c_obj *
-create_most_c_obj(const char *name, struct kobject *parent)
-{
-	struct most_c_obj *c;
-	int retval;
-
-	c = kzalloc(sizeof(*c), GFP_KERNEL);
-	if (!c)
-		return NULL;
-	c->kobj.kset = most_channel_kset;
-	retval = kobject_init_and_add(&c->kobj, &most_channel_ktype, parent,
-				      "%s", name);
-	if (retval) {
-		kobject_put(&c->kobj);
-		return NULL;
-	}
-	kobject_uevent(&c->kobj, KOBJ_ADD);
-	return c;
-}
+static const struct attribute_group *channel_attr_groups[] = {
+	&channel_attr_group,
+	NULL,
+};
 
 /*		     ___	       ___
  *		     ___I N S T A N C E___
@@ -552,103 +494,22 @@ static ssize_t set_packets_per_xact_store(struct most_c_obj *c,
 
 static struct list_head instance_list;
 
-/**
- * struct most_inst_attribute - to access the attributes of instance object
- * @attr: attributes of an instance
- * @show: pointer to the show function
- * @store: pointer to the store function
- */
-struct most_inst_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct most_inst_obj *d,
-			struct most_inst_attribute *attr,
-			char *buf);
-	ssize_t (*store)(struct most_inst_obj *d,
-			 struct most_inst_attribute *attr,
-			 const char *buf,
-			 size_t count);
-};
-
-#define to_instance_attr(a) \
-	container_of(a, struct most_inst_attribute, attr)
-
-/**
- * instance_attr_show - show function for an instance object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- */
-static ssize_t instance_attr_show(struct kobject *kobj,
-				  struct attribute *attr,
-				  char *buf)
-{
-	struct most_inst_attribute *instance_attr;
-	struct most_inst_obj *instance_obj;
-
-	instance_attr = to_instance_attr(attr);
-	instance_obj = to_inst_obj(kobj);
-
-	if (!instance_attr->show)
-		return -EIO;
-
-	return instance_attr->show(instance_obj, instance_attr, buf);
-}
-
-/**
- * instance_attr_store - store function for an instance object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- * @len: length of buffer
- */
-static ssize_t instance_attr_store(struct kobject *kobj,
-				   struct attribute *attr,
-				   const char *buf,
-				   size_t len)
-{
-	struct most_inst_attribute *instance_attr;
-	struct most_inst_obj *instance_obj;
-
-	instance_attr = to_instance_attr(attr);
-	instance_obj = to_inst_obj(kobj);
-
-	if (!instance_attr->store)
-		return -EIO;
-
-	return instance_attr->store(instance_obj, instance_attr, buf, len);
-}
-
-static const struct sysfs_ops most_inst_sysfs_ops = {
-	.show = instance_attr_show,
-	.store = instance_attr_store,
-};
-
-/**
- * most_inst_release - release function for instance object
- * @kobj: pointer to instance's kobject
- *
- * This frees the allocated memory for the instance object
- */
-static void most_inst_release(struct kobject *kobj)
-{
-	struct most_inst_obj *inst = to_inst_obj(kobj);
-
-	kfree(inst);
-}
-
-static ssize_t description_show(struct most_inst_obj *instance_obj,
-				struct most_inst_attribute *attr,
+static ssize_t description_show(struct device *dev,
+				struct device_attribute *attr,
 				char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%s\n",
-			instance_obj->iface->description);
+	struct most_interface *iface = to_most_interface(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", iface->description);
 }
 
-static ssize_t interface_show(struct most_inst_obj *instance_obj,
-			      struct most_inst_attribute *attr,
+static ssize_t interface_show(struct device *dev,
+			      struct device_attribute *attr,
 			      char *buf)
 {
-	switch (instance_obj->iface->interface) {
+	struct most_interface *iface = to_most_interface(dev);
+
+	switch (iface->interface) {
 	case ITYPE_LOOPBACK:
 		return snprintf(buf, PAGE_SIZE, "loopback\n");
 	case ITYPE_I2C:
@@ -671,182 +532,45 @@ static ssize_t interface_show(struct most_inst_obj *instance_obj,
 	return snprintf(buf, PAGE_SIZE, "unknown\n");
 }
 
-static struct most_inst_attribute most_inst_attr_description =
-	__ATTR_RO(description);
+static DEVICE_ATTR_RO(description);
+static DEVICE_ATTR_RO(interface);
 
-static struct most_inst_attribute most_inst_attr_interface =
-	__ATTR_RO(interface);
-
-static struct attribute *most_inst_def_attrs[] = {
-	&most_inst_attr_description.attr,
-	&most_inst_attr_interface.attr,
+static struct attribute *interface_attrs[] = {
+	DEV_ATTR(description),
+	DEV_ATTR(interface),
 	NULL,
 };
 
-static struct kobj_type most_inst_ktype = {
-	.sysfs_ops = &most_inst_sysfs_ops,
-	.release = most_inst_release,
-	.default_attrs = most_inst_def_attrs,
+static struct attribute_group interface_attr_group = {
+	.attrs = interface_attrs,
 };
 
-static struct kset *most_inst_kset;
-
-/**
- * create_most_inst_obj - creates an instance object
- * @name: name of the object to be created
- *
- * This allocates memory for an instance structure, assigns the proper kset
- * and registers it with sysfs.
- *
- * Returns a pointer to the instance object or NULL when something went wrong.
- */
-static struct most_inst_obj *create_most_inst_obj(const char *name)
-{
-	struct most_inst_obj *inst;
-	int retval;
-
-	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
-	if (!inst)
-		return NULL;
-	inst->kobj.kset = most_inst_kset;
-	retval = kobject_init_and_add(&inst->kobj, &most_inst_ktype, NULL,
-				      "%s", name);
-	if (retval) {
-		kobject_put(&inst->kobj);
-		return NULL;
-	}
-	kobject_uevent(&inst->kobj, KOBJ_ADD);
-	return inst;
-}
-
-/**
- * destroy_most_inst_obj - MOST instance release function
- * @inst: pointer to the instance object
- *
- * This decrements the reference counter of the instance object.
- * If the reference count turns zero, its release function is called
- */
-static void destroy_most_inst_obj(struct most_inst_obj *inst)
-{
-	struct most_c_obj *c, *tmp;
+static const struct attribute_group *interface_attr_groups[] = {
+	&interface_attr_group,
+	NULL,
+};
 
-	list_for_each_entry_safe(c, tmp, &inst->channel_list, list) {
-		flush_trash_fifo(c);
-		flush_channel_fifos(c);
-		kobject_put(&c->kobj);
-	}
-	kobject_put(&inst->kobj);
-}
 
 /*		     ___     ___
  *		     ___A I M___
  */
-struct most_aim_obj {
-	struct kobject kobj;
-	struct list_head list;
-	struct most_aim *driver;
-};
-
-#define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj)
-
 static struct list_head aim_list;
 
-/**
- * struct most_aim_attribute - to access the attributes of AIM object
- * @attr: attributes of an AIM
- * @show: pointer to the show function
- * @store: pointer to the store function
- */
-struct most_aim_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct most_aim_obj *d,
-			struct most_aim_attribute *attr,
-			char *buf);
-	ssize_t (*store)(struct most_aim_obj *d,
-			 struct most_aim_attribute *attr,
-			 const char *buf,
-			 size_t count);
-};
-
-#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr)
-
-/**
- * aim_attr_show - show function of an AIM object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- */
-static ssize_t aim_attr_show(struct kobject *kobj,
-			     struct attribute *attr,
-			     char *buf)
-{
-	struct most_aim_attribute *aim_attr;
-	struct most_aim_obj *aim_obj;
-
-	aim_attr = to_aim_attr(attr);
-	aim_obj = to_aim_obj(kobj);
-
-	if (!aim_attr->show)
-		return -EIO;
-
-	return aim_attr->show(aim_obj, aim_attr, buf);
-}
-
-/**
- * aim_attr_store - store function of an AIM object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- * @len: length of buffer
- */
-static ssize_t aim_attr_store(struct kobject *kobj,
-			      struct attribute *attr,
-			      const char *buf,
-			      size_t len)
-{
-	struct most_aim_attribute *aim_attr;
-	struct most_aim_obj *aim_obj;
-
-	aim_attr = to_aim_attr(attr);
-	aim_obj = to_aim_obj(kobj);
-
-	if (!aim_attr->store)
-		return -EIO;
-	return aim_attr->store(aim_obj, aim_attr, buf, len);
-}
-
-static const struct sysfs_ops most_aim_sysfs_ops = {
-	.show = aim_attr_show,
-	.store = aim_attr_store,
-};
-
-/**
- * most_aim_release - AIM release function
- * @kobj: pointer to AIM's kobject
- */
-static void most_aim_release(struct kobject *kobj)
-{
-	struct most_aim_obj *aim_obj = to_aim_obj(kobj);
-
-	kfree(aim_obj);
-}
-
-static ssize_t links_show(struct most_aim_obj *aim_obj,
-			  struct most_aim_attribute *attr,
+static ssize_t links_show(struct device *dev, struct device_attribute *attr,
 			  char *buf)
 {
 	struct most_c_obj *c;
 	struct most_inst_obj *i;
+	struct most_aim *aim = to_most_aim(dev);
 	int offs = 0;
 
 	list_for_each_entry(i, &instance_list, list) {
 		list_for_each_entry(c, &i->channel_list, list) {
-			if (c->aim0.ptr == aim_obj->driver ||
-			    c->aim1.ptr == aim_obj->driver) {
+			if (c->aim0.ptr == aim || c->aim1.ptr == aim) {
 				offs += snprintf(buf + offs, PAGE_SIZE - offs,
 						 "%s:%s\n",
-						 kobject_name(&i->kobj),
-						 kobject_name(&c->kobj));
+						 dev_name(&i->iface->dev),
+						 dev_name(&c->dev));
 			}
 		}
 	}
@@ -899,15 +623,14 @@ static int split_string(char *buf, char **a, char **b, char **c)
  *
  * This retrieves the pointer to a channel object.
  */
-static struct
-most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
+static struct most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
 {
 	struct most_c_obj *c, *tmp;
 	struct most_inst_obj *i, *i_tmp;
 	int found = 0;
 
 	list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
-		if (!strcmp(kobject_name(&i->kobj), mdev)) {
+		if (!strcmp(dev_name(&i->iface->dev), mdev)) {
 			found++;
 			break;
 		}
@@ -916,7 +639,7 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
 		return ERR_PTR(-EIO);
 
 	list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
-		if (!strcmp(kobject_name(&c->kobj), mdev_ch)) {
+		if (!strcmp(dev_name(&c->dev), mdev_ch)) {
 			found++;
 			break;
 		}
@@ -926,6 +649,30 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
 	return c;
 }
 
+static int link_channel_to_aim(struct most_c_obj *c, struct most_aim *aim,
+			       char *aim_param)
+{
+	int ret;
+	struct most_aim **aim_ptr;
+
+	if (!c->aim0.ptr)
+		aim_ptr = &c->aim0.ptr;
+	else if (!c->aim1.ptr)
+		aim_ptr = &c->aim1.ptr;
+	else
+		return -ENOSPC;
+
+	*aim_ptr = aim;
+	ret = aim->probe_channel(c->iface, c->channel_id,
+				 &c->cfg, aim_param);
+	if (ret) {
+		*aim_ptr = NULL;
+		return ret;
+	}
+
+	return 0;
+}
+
 /**
  * add_link_store - store() function for add_link attribute
  * @aim_obj: pointer to AIM object
@@ -948,13 +695,13 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
  * (1) would create the device node /dev/my_rxchannel
  * (2) would create the device node /dev/mdev1-ep81
  */
-static ssize_t add_link_store(struct most_aim_obj *aim_obj,
-			      struct most_aim_attribute *attr,
+static ssize_t add_link_store(struct device *dev,
+			      struct device_attribute *attr,
 			      const char *buf,
 			      size_t len)
 {
 	struct most_c_obj *c;
-	struct most_aim **aim_ptr;
+	struct most_aim *aim = to_most_aim(dev);
 	char buffer[STRING_SIZE];
 	char *mdev;
 	char *mdev_ch;
@@ -979,20 +726,9 @@ static ssize_t add_link_store(struct most_aim_obj *aim_obj,
 	if (IS_ERR(c))
 		return -ENODEV;
 
-	if (!c->aim0.ptr)
-		aim_ptr = &c->aim0.ptr;
-	else if (!c->aim1.ptr)
-		aim_ptr = &c->aim1.ptr;
-	else
-		return -ENOSPC;
-
-	*aim_ptr = aim_obj->driver;
-	ret = aim_obj->driver->probe_channel(c->iface, c->channel_id,
-					     &c->cfg, &c->kobj, mdev_devnod);
-	if (ret) {
-		*aim_ptr = NULL;
+	ret = link_channel_to_aim(c, aim, mdev_devnod);
+	if (ret)
 		return ret;
-	}
 
 	return len;
 }
@@ -1007,12 +743,13 @@ static ssize_t add_link_store(struct most_aim_obj *aim_obj,
  * Example:
  * echo "mdev0:ep81" >remove_link
  */
-static ssize_t remove_link_store(struct most_aim_obj *aim_obj,
-				 struct most_aim_attribute *attr,
+static ssize_t remove_link_store(struct device *dev,
+				 struct device_attribute *attr,
 				 const char *buf,
 				 size_t len)
 {
 	struct most_c_obj *c;
+	struct most_aim *aim = to_most_aim(dev);
 	char buffer[STRING_SIZE];
 	char *mdev;
 	char *mdev_ch;
@@ -1028,94 +765,38 @@ static ssize_t remove_link_store(struct most_aim_obj *aim_obj,
 	if (IS_ERR(c))
 		return -ENODEV;
 
-	if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id))
+	if (aim->disconnect_channel(c->iface, c->channel_id))
 		return -EIO;
-	if (c->aim0.ptr == aim_obj->driver)
+	if (c->aim0.ptr == aim)
 		c->aim0.ptr = NULL;
-	if (c->aim1.ptr == aim_obj->driver)
+	if (c->aim1.ptr == aim)
 		c->aim1.ptr = NULL;
 	return len;
 }
 
-static struct most_aim_attribute most_aim_attrs[] = {
-	__ATTR_RO(links),
-	__ATTR_WO(add_link),
-	__ATTR_WO(remove_link),
-};
+static DEVICE_ATTR_RO(links);
+static DEVICE_ATTR_WO(add_link);
+static DEVICE_ATTR_WO(remove_link);
 
-static struct attribute *most_aim_def_attrs[] = {
-	&most_aim_attrs[0].attr,
-	&most_aim_attrs[1].attr,
-	&most_aim_attrs[2].attr,
+static struct attribute *aim_attrs[] = {
+	DEV_ATTR(links),
+	DEV_ATTR(add_link),
+	DEV_ATTR(remove_link),
 	NULL,
 };
 
-static struct kobj_type most_aim_ktype = {
-	.sysfs_ops = &most_aim_sysfs_ops,
-	.release = most_aim_release,
-	.default_attrs = most_aim_def_attrs,
+static struct attribute_group aim_attr_group = {
+	.attrs = aim_attrs,
 };
 
-static struct kset *most_aim_kset;
-
-/**
- * create_most_aim_obj - creates an AIM object
- * @name: name of the AIM
- *
- * This creates an AIM object assigns the proper kset and registers
- * it with sysfs.
- * Returns a pointer to the object or NULL if something went wrong.
- */
-static struct most_aim_obj *create_most_aim_obj(const char *name)
-{
-	struct most_aim_obj *most_aim;
-	int retval;
-
-	most_aim = kzalloc(sizeof(*most_aim), GFP_KERNEL);
-	if (!most_aim)
-		return NULL;
-	most_aim->kobj.kset = most_aim_kset;
-	retval = kobject_init_and_add(&most_aim->kobj, &most_aim_ktype,
-				      NULL, "%s", name);
-	if (retval) {
-		kobject_put(&most_aim->kobj);
-		return NULL;
-	}
-	kobject_uevent(&most_aim->kobj, KOBJ_ADD);
-	return most_aim;
-}
-
-/**
- * destroy_most_aim_obj - AIM release function
- * @p: pointer to AIM object
- *
- * This decrements the reference counter of the AIM object. If the
- * reference count turns zero, its release function will be called.
- */
-static void destroy_most_aim_obj(struct most_aim_obj *p)
-{
-	kobject_put(&p->kobj);
-}
-
+static const struct attribute_group *aim_attr_groups[] = {
+	&aim_attr_group,
+	NULL,
+};
 /*		     ___       ___
  *		     ___C O R E___
  */
 
-/**
- * Instantiation of the MOST bus
- */
-static struct bus_type most_bus = {
-	.name = "most",
-};
-
-/**
- * Instantiation of the core driver
- */
-static struct device_driver mostcore = {
-	.name = "mostcore",
-	.bus = &most_bus,
-};
-
 static inline void trash_mbo(struct mbo *mbo)
 {
 	unsigned long flags;
@@ -1334,37 +1015,10 @@ static void most_write_completion(struct mbo *mbo)
 		arm_mbo(mbo);
 }
 
-/**
- * get_channel_by_iface - get pointer to channel object
- * @iface: pointer to interface instance
- * @id: channel ID
- *
- * This retrieves a pointer to a channel of the given interface and channel ID.
- */
-static struct
-most_c_obj *get_channel_by_iface(struct most_interface *iface, int id)
-{
-	struct most_inst_obj *i;
-
-	if (unlikely(!iface)) {
-		pr_err("Bad interface\n");
-		return NULL;
-	}
-	if (unlikely((id < 0) || (id >= iface->num_channels))) {
-		pr_err("Channel index (%d) out of range\n", id);
-		return NULL;
-	}
-	i = iface->priv;
-	if (unlikely(!i)) {
-		pr_err("interface is not registered\n");
-		return NULL;
-	}
-	return i->channel[id];
-}
-
 int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim)
 {
-	struct most_c_obj *c = get_channel_by_iface(iface, id);
+	struct most_inst_obj *inst = iface->priv;
+	struct most_c_obj *c = inst->channel[id];
 	unsigned long flags;
 	int empty;
 
@@ -1396,10 +1050,11 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id,
 {
 	struct mbo *mbo;
 	struct most_c_obj *c;
+	struct most_inst_obj *inst = iface->priv;
 	unsigned long flags;
 	int *num_buffers_ptr;
 
-	c = get_channel_by_iface(iface, id);
+	c = inst->channel[id];
 	if (unlikely(!c))
 		return NULL;
 
@@ -1501,7 +1156,8 @@ int most_start_channel(struct most_interface *iface, int id,
 {
 	int num_buffer;
 	int ret;
-	struct most_c_obj *c = get_channel_by_iface(iface, id);
+	struct most_inst_obj *inst = iface->priv;
+	struct most_c_obj *c = inst->channel[id];
 
 	if (unlikely(!c))
 		return -EINVAL;
@@ -1569,13 +1225,15 @@ int most_start_channel(struct most_interface *iface, int id,
 int most_stop_channel(struct most_interface *iface, int id,
 		      struct most_aim *aim)
 {
+	struct most_inst_obj *inst;
 	struct most_c_obj *c;
 
 	if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) {
 		pr_err("Bad interface or index out of range\n");
 		return -EINVAL;
 	}
-	c = get_channel_by_iface(iface, id);
+	inst = iface->priv;
+	c = inst->channel[id];
 	if (unlikely(!c))
 		return -EINVAL;
 
@@ -1621,28 +1279,34 @@ int most_stop_channel(struct most_interface *iface, int id,
 }
 EXPORT_SYMBOL_GPL(most_stop_channel);
 
+void release_aim(struct device *dev)
+{
+	pr_info("releasing aim %s\n", dev_name(dev));
+}
+
 /**
  * most_register_aim - registers an AIM (driver) with the core
  * @aim: instance of AIM to be registered
  */
 int most_register_aim(struct most_aim *aim)
 {
-	struct most_aim_obj *aim_obj;
+	int ret;
 
 	if (!aim) {
 		pr_err("Bad driver\n");
 		return -EINVAL;
 	}
-	aim_obj = create_most_aim_obj(aim->name);
-	if (!aim_obj) {
-		pr_info("failed to alloc driver object\n");
-		return -ENOMEM;
+	aim->dev.init_name = aim->name;
+	aim->dev.bus = &most_bus_type;
+	aim->dev.parent = &core_dev;
+	aim->dev.groups = aim_attr_groups;
+	aim->dev.release = release_aim;
+	ret = device_register(&aim->dev);
+	if (ret) {
+		pr_err("registering device %s failed\n", aim->name);
+		return ret;
 	}
-	aim_obj->driver = aim;
-	aim->context = aim_obj;
-	pr_info("registered new application interfacing module %s\n",
-		aim->name);
-	list_add_tail(&aim_obj->list, &aim_list);
+	pr_info("registered new application interfacing module %s\n", aim->name);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(most_register_aim);
@@ -1653,7 +1317,6 @@ int most_register_aim(struct most_aim *aim)
  */
 int most_deregister_aim(struct most_aim *aim)
 {
-	struct most_aim_obj *aim_obj;
 	struct most_c_obj *c, *tmp;
 	struct most_inst_obj *i, *i_tmp;
 
@@ -1662,11 +1325,6 @@ int most_deregister_aim(struct most_aim *aim)
 		return -EINVAL;
 	}
 
-	aim_obj = aim->context;
-	if (!aim_obj) {
-		pr_info("driver not registered.\n");
-		return -EINVAL;
-	}
 	list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
 		list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
 			if (c->aim0.ptr == aim || c->aim1.ptr == aim)
@@ -1678,13 +1336,22 @@ int most_deregister_aim(struct most_aim *aim)
 				c->aim1.ptr = NULL;
 		}
 	}
-	list_del(&aim_obj->list);
-	destroy_most_aim_obj(aim_obj);
+	device_unregister(&aim->dev);
 	pr_info("deregistering application interfacing module %s\n", aim->name);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(most_deregister_aim);
 
+static void release_interface(struct device *dev)
+{
+	pr_info("releasing interface dev %s...\n", dev_name(dev));
+}
+
+static void release_channel(struct device *dev)
+{
+	pr_info("releasing channel dev %s...\n", dev_name(dev));
+}
+
 /**
  * most_register_interface - registers an interface with core
  * @iface: pointer to the instance of the interface description.
@@ -1692,7 +1359,7 @@ int most_deregister_aim(struct most_aim *aim)
  * Allocates and initializes a new interface instance and all of its channels.
  * Returns a pointer to kobject or an error pointer.
  */
-struct kobject *most_register_interface(struct most_interface *iface)
+int most_register_interface(struct most_interface *iface)
 {
 	unsigned int i;
 	int id;
@@ -1704,21 +1371,20 @@ struct kobject *most_register_interface(struct most_interface *iface)
 	if (!iface || !iface->enqueue || !iface->configure ||
 	    !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) {
 		pr_err("Bad interface or channel overflow\n");
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 	}
 
 	id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL);
 	if (id < 0) {
 		pr_info("Failed to alloc mdev ID\n");
-		return ERR_PTR(id);
+		return id;
 	}
-	snprintf(name, STRING_SIZE, "mdev%d", id);
 
-	inst = create_most_inst_obj(name);
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
 	if (!inst) {
 		pr_info("Failed to allocate interface instance\n");
 		ida_simple_remove(&mdev_id, id);
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	iface->priv = inst;
@@ -1726,6 +1392,18 @@ struct kobject *most_register_interface(struct most_interface *iface)
 	inst->iface = iface;
 	inst->dev_id = id;
 	list_add_tail(&inst->list, &instance_list);
+	snprintf(name, STRING_SIZE, "mdev%d", id);
+	iface->dev.init_name = name;
+	iface->dev.bus = &most_bus_type;
+	iface->dev.parent = &core_dev;
+	iface->dev.groups = interface_attr_groups;
+	iface->dev.release = release_interface;
+	if (device_register(&iface->dev)) {
+		pr_err("registering iface->dev failed\n");
+		kfree(inst);
+		ida_simple_remove(&mdev_id, id);
+		return -ENOMEM;
+	}
 
 	for (i = 0; i < iface->num_channels; i++) {
 		const char *name_suffix = iface->channel_vector[i].name_suffix;
@@ -1736,9 +1414,18 @@ struct kobject *most_register_interface(struct most_interface *iface)
 			snprintf(channel_name, STRING_SIZE, "%s", name_suffix);
 
 		/* this increments the reference count of this instance */
-		c = create_most_c_obj(channel_name, &inst->kobj);
+		c = kzalloc(sizeof(*c), GFP_KERNEL);
 		if (!c)
 			goto free_instance;
+		//snprintf(c->dev.init_name, STRING_SIZE, channel_name);
+		c->dev.init_name = channel_name;
+		c->dev.parent = &iface->dev;
+		c->dev.groups = channel_attr_groups;
+		c->dev.release = release_channel;
+		if (device_register(&c->dev)) {
+			pr_err("registering c->dev failed\n");
+			goto free_instance;
+		}
 		inst->channel[i] = c;
 		c->is_starving = 0;
 		c->iface = iface;
@@ -1764,15 +1451,14 @@ struct kobject *most_register_interface(struct most_interface *iface)
 		list_add_tail(&c->list, &inst->channel_list);
 	}
 	pr_info("registered new MOST device mdev%d (%s)\n",
-		inst->dev_id, iface->description);
-	return &inst->kobj;
+		id, iface->description);
+	return 0;
 
 free_instance:
 	pr_info("Failed allocate channel(s)\n");
-	list_del(&inst->list);
+	device_unregister(&iface->dev);
 	ida_simple_remove(&mdev_id, id);
-	destroy_most_inst_obj(inst);
-	return ERR_PTR(-ENOMEM);
+	return -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(most_register_interface);
 
@@ -1785,17 +1471,14 @@ struct kobject *most_register_interface(struct most_interface *iface)
  */
 void most_deregister_interface(struct most_interface *iface)
 {
-	struct most_inst_obj *i = iface->priv;
+	int i;
 	struct most_c_obj *c;
+	struct most_inst_obj *inst;
 
-	if (unlikely(!i)) {
-		pr_info("Bad Interface\n");
-		return;
-	}
-	pr_info("deregistering MOST device %s (%s)\n", i->kobj.name,
-		iface->description);
-
-	list_for_each_entry(c, &i->channel_list, list) {
+	pr_info("deregistering MOST device %s (%s)\n", dev_name(&iface->dev), iface->description);
+	inst = iface->priv;
+	for (i = 0; i < iface->num_channels; i++) {
+		c = inst->channel[i];
 		if (c->aim0.ptr)
 			c->aim0.ptr->disconnect_channel(c->iface,
 							c->channel_id);
@@ -1804,11 +1487,14 @@ void most_deregister_interface(struct most_interface *iface)
 							c->channel_id);
 		c->aim0.ptr = NULL;
 		c->aim1.ptr = NULL;
+		list_del(&c->list);
+		device_unregister(&c->dev);
+		kfree(c);
 	}
 
-	ida_simple_remove(&mdev_id, i->dev_id);
-	list_del(&i->list);
-	destroy_most_inst_obj(i);
+	ida_simple_remove(&mdev_id, inst->dev_id);
+	kfree(inst);
+	device_unregister(&iface->dev);
 }
 EXPORT_SYMBOL_GPL(most_deregister_interface);
 
@@ -1824,7 +1510,8 @@ void most_deregister_interface(struct most_interface *iface)
  */
 void most_stop_enqueue(struct most_interface *iface, int id)
 {
-	struct most_c_obj *c = get_channel_by_iface(iface, id);
+	struct most_inst_obj *inst = iface->priv;
+	struct most_c_obj *c = inst->channel[id];
 
 	if (!c)
 		return;
@@ -1845,7 +1532,8 @@ void most_stop_enqueue(struct most_interface *iface, int id)
  */
 void most_resume_enqueue(struct most_interface *iface, int id)
 {
-	struct most_c_obj *c = get_channel_by_iface(iface, id);
+	struct most_inst_obj *inst = iface->priv;
+	struct most_c_obj *c = inst->channel[id];
 
 	if (!c)
 		return;
@@ -1858,6 +1546,11 @@ void most_resume_enqueue(struct most_interface *iface, int id)
 }
 EXPORT_SYMBOL_GPL(most_resume_enqueue);
 
+static void release_most_sub(struct device *dev)
+{
+	pr_info("releasing most_subsystem\n");
+}
+
 static int __init most_init(void)
 {
 	int err;
@@ -1867,12 +1560,11 @@ static int __init most_init(void)
 	INIT_LIST_HEAD(&aim_list);
 	ida_init(&mdev_id);
 
-	err = bus_register(&most_bus);
+	err = bus_register(&most_bus_type);
 	if (err) {
 		pr_info("Cannot register most bus\n");
 		return err;
 	}
-
 	most_class = class_create(THIS_MODULE, "most");
 	if (IS_ERR(most_class)) {
 		pr_info("No udev support.\n");
@@ -1885,60 +1577,30 @@ static int __init most_init(void)
 		pr_info("Cannot register core driver\n");
 		goto exit_class;
 	}
-
-	core_dev = device_create(most_class, NULL, 0, NULL, "mostcore");
-	if (IS_ERR(core_dev)) {
-		err = PTR_ERR(core_dev);
-		goto exit_driver;
-	}
-
-	most_aim_kset = kset_create_and_add("aims", NULL, &core_dev->kobj);
-	if (!most_aim_kset) {
+	core_dev.init_name = "most_bus";
+	core_dev.release = release_most_sub;
+	if (device_register(&core_dev)) {
 		err = -ENOMEM;
-		goto exit_class_container;
-	}
-
-	most_inst_kset = kset_create_and_add("devices", NULL, &core_dev->kobj);
-	if (!most_inst_kset) {
-		err = -ENOMEM;
-		goto exit_driver_kset;
+		goto exit_driver;
 	}
-
 	return 0;
 
-exit_driver_kset:
-	kset_unregister(most_aim_kset);
-exit_class_container:
-	device_destroy(most_class, 0);
 exit_driver:
 	driver_unregister(&mostcore);
 exit_class:
 	class_destroy(most_class);
 exit_bus:
-	bus_unregister(&most_bus);
+	bus_unregister(&most_bus_type);
 	return err;
 }
 
 static void __exit most_exit(void)
 {
-	struct most_inst_obj *i, *i_tmp;
-	struct most_aim_obj *d, *d_tmp;
-
 	pr_info("exit core module\n");
-	list_for_each_entry_safe(d, d_tmp, &aim_list, list) {
-		destroy_most_aim_obj(d);
-	}
-
-	list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
-		list_del(&i->list);
-		destroy_most_inst_obj(i);
-	}
-	kset_unregister(most_inst_kset);
-	kset_unregister(most_aim_kset);
-	device_destroy(most_class, 0);
+	device_unregister(&core_dev);
 	driver_unregister(&mostcore);
 	class_destroy(most_class);
-	bus_unregister(&most_bus);
+	bus_unregister(&most_bus_type);
 	ida_destroy(&mdev_id);
 }
 
diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h
index a6e618c..588aadb 100644
--- a/drivers/staging/most/core.h
+++ b/drivers/staging/most/core.h
@@ -238,6 +238,7 @@ struct mbo {
  * @priv Private field used by mostcore to store context information.
  */
 struct most_interface {
+	struct device dev;
 	struct module *mod;
 	enum most_interface_type interface;
 	const char *description;
@@ -255,6 +256,7 @@ struct most_interface {
 	void *priv;
 };
 
+#define to_most_interface(d) container_of(d, struct most_interface, dev)
 /**
  * struct most_aim - identifies MOST device driver to mostcore
  * @name: Driver name
@@ -265,10 +267,10 @@ struct most_interface {
  * @context: context pointer to be used by mostcore
  */
 struct most_aim {
+	struct device dev;
 	const char *name;
 	int (*probe_channel)(struct most_interface *iface, int channel_idx,
-			     struct most_channel_config *cfg,
-			     struct kobject *parent, char *name);
+			     struct most_channel_config *cfg, char *name);
 	int (*disconnect_channel)(struct most_interface *iface,
 				  int channel_idx);
 	int (*rx_completion)(struct mbo *mbo);
@@ -276,6 +278,7 @@ struct most_aim {
 	void *context;
 };
 
+#define to_most_aim(d) container_of(d, struct most_aim, dev)
 /**
  * most_register_interface - Registers instance of the interface.
  * @iface: Pointer to the interface instance description.
@@ -285,7 +288,7 @@ struct most_aim {
  * Note: HDM has to ensure that any reference held on the kobj is
  * released before deregistering the interface.
  */
-struct kobject *most_register_interface(struct most_interface *iface);
+int most_register_interface(struct most_interface *iface);
 
 /**
  * Deregisters instance of the interface.
diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c
index cc8563f..309ef13 100644
--- a/drivers/staging/most/dim2/dim2.c
+++ b/drivers/staging/most/dim2/dim2.c
@@ -93,6 +93,7 @@ struct hdm_channel {
  * @atx_idx: index of async tx channel
  */
 struct dim2_hdm {
+	struct device dev;
 	struct hdm_channel hch[DMA_CHANNELS];
 	struct most_channel_capability capabilities[DMA_CHANNELS];
 	struct most_interface most_iface;
@@ -744,7 +745,6 @@ static int dim2_probe(struct platform_device *pdev)
 	struct dim2_hdm *dev;
 	struct resource *res;
 	int ret, i;
-	struct kobject *kobj;
 	int irq;
 
 	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
@@ -832,18 +832,20 @@ static int dim2_probe(struct platform_device *pdev)
 	dev->most_iface.enqueue = enqueue;
 	dev->most_iface.poison_channel = poison_channel;
 	dev->most_iface.request_netinfo = request_netinfo;
+	dev->dev.init_name = "dim2_state";
+	dev->dev.parent = &dev->most_iface.dev;
 
-	kobj = most_register_interface(&dev->most_iface);
-	if (IS_ERR(kobj)) {
-		ret = PTR_ERR(kobj);
+	ret = most_register_interface(&dev->most_iface);
+	if (ret) {
 		dev_err(&pdev->dev, "failed to register MOST interface\n");
 		goto err_stop_thread;
 	}
 
-	ret = dim2_sysfs_probe(&dev->bus, kobj);
-	if (ret)
+	ret = dim2_sysfs_probe(&dev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to create sysfs attribute\n");
 		goto err_unreg_iface;
-
+	}
 	ret = startup_dim(pdev);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to initialize DIM2\n");
@@ -853,7 +855,7 @@ static int dim2_probe(struct platform_device *pdev)
 	return 0;
 
 err_destroy_bus:
-	dim2_sysfs_destroy(&dev->bus);
+	dim2_sysfs_destroy(&dev->dev);
 err_unreg_iface:
 	most_deregister_interface(&dev->most_iface);
 err_stop_thread:
@@ -881,7 +883,7 @@ static int dim2_remove(struct platform_device *pdev)
 	if (pdata && pdata->destroy)
 		pdata->destroy(pdata);
 
-	dim2_sysfs_destroy(&dev->bus);
+	dim2_sysfs_destroy(&dev->dev);
 	most_deregister_interface(&dev->most_iface);
 	kthread_stop(dev->netinfo_task);
 
diff --git a/drivers/staging/most/dim2/sysfs.c b/drivers/staging/most/dim2/sysfs.c
index 1331cf0..5ab0c02 100644
--- a/drivers/staging/most/dim2/sysfs.c
+++ b/drivers/staging/most/dim2/sysfs.c
@@ -17,99 +17,39 @@
 
 #include <linux/kernel.h>
 #include "sysfs.h"
+#include <linux/device.h>
 
-struct bus_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct medialb_bus *bus, char *buf);
-	ssize_t (*store)(struct medialb_bus *bus, const char *buf,
-			 size_t count);
-};
-
-static ssize_t state_show(struct medialb_bus *bus, char *buf)
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
 	bool state = dim2_sysfs_get_state_cb();
 
 	return sprintf(buf, "%s\n", state ? "locked" : "");
 }
 
-static struct bus_attr state_attr = __ATTR_RO(state);
+DEVICE_ATTR_RO(state);
 
-static struct attribute *bus_default_attrs[] = {
-	&state_attr.attr,
+static struct attribute *dev_attrs[] = {
+	&dev_attr_state.attr,
 	NULL,
 };
 
-static const struct attribute_group bus_attr_group = {
-	.attrs = bus_default_attrs,
+static struct attribute_group dev_attr_group = {
+	.attrs = dev_attrs,
 };
 
-static void bus_kobj_release(struct kobject *kobj)
-{
-}
-
-static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr,
-				  char *buf)
-{
-	struct medialb_bus *bus =
-		container_of(kobj, struct medialb_bus, kobj_group);
-	struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
-
-	if (!xattr->show)
-		return -EIO;
-
-	return xattr->show(bus, buf);
-}
-
-static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr,
-				   const char *buf, size_t count)
-{
-	struct medialb_bus *bus =
-		container_of(kobj, struct medialb_bus, kobj_group);
-	struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
-
-	if (!xattr->store)
-		return -EIO;
-
-	return xattr->store(bus, buf, count);
-}
-
-static struct sysfs_ops const bus_kobj_sysfs_ops = {
-	.show = bus_kobj_attr_show,
-	.store = bus_kobj_attr_store,
-};
-
-static struct kobj_type bus_ktype = {
-	.release = bus_kobj_release,
-	.sysfs_ops = &bus_kobj_sysfs_ops,
+static const struct attribute_group *dev_attr_groups[] = {
+	&dev_attr_group,
+	NULL,
 };
 
-int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj)
+int dim2_sysfs_probe(struct device *dev)
 {
-	int err;
-
-	kobject_init(&bus->kobj_group, &bus_ktype);
-	err = kobject_add(&bus->kobj_group, parent_kobj, "bus");
-	if (err) {
-		pr_err("kobject_add() failed: %d\n", err);
-		goto err_kobject_add;
-	}
-
-	err = sysfs_create_group(&bus->kobj_group, &bus_attr_group);
-	if (err) {
-		pr_err("sysfs_create_group() failed: %d\n", err);
-		goto err_create_group;
-	}
-
-	return 0;
-
-err_create_group:
-	kobject_put(&bus->kobj_group);
-
-err_kobject_add:
-	return err;
+	dev->groups = dev_attr_groups;
+	return device_register(dev);
 }
 
-void dim2_sysfs_destroy(struct medialb_bus *bus)
+void dim2_sysfs_destroy(struct device *dev)
 {
-	kobject_put(&bus->kobj_group);
+	device_unregister(dev);
 }
diff --git a/drivers/staging/most/dim2/sysfs.h b/drivers/staging/most/dim2/sysfs.h
index 236de47..070a70c 100644
--- a/drivers/staging/most/dim2/sysfs.h
+++ b/drivers/staging/most/dim2/sysfs.h
@@ -22,10 +22,10 @@ struct medialb_bus {
 	struct kobject kobj_group;
 };
 
-struct dim2_hdm;
+struct device;
 
-int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj);
-void dim2_sysfs_destroy(struct medialb_bus *bus);
+int dim2_sysfs_probe(struct device *dev);
+void dim2_sysfs_destroy(struct device *dev);
 
 /*
  * callback,
diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c
index 0a3e858..587ac86 100644
--- a/drivers/staging/most/i2c/i2c.c
+++ b/drivers/staging/most/i2c/i2c.c
@@ -309,7 +309,6 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct hdm_i2c *dev;
 	int ret, i;
-	struct kobject *kobj;
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev)
@@ -347,11 +346,11 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	dev->client = client;
 	i2c_set_clientdata(client, dev);
 
-	kobj = most_register_interface(&dev->most_iface);
-	if (IS_ERR(kobj)) {
+	ret = most_register_interface(&dev->most_iface);
+	if (ret) {
 		pr_err("Failed to register i2c as a MOST interface\n");
 		kfree(dev);
-		return PTR_ERR(kobj);
+		return ret;
 	}
 
 	dev->polling_mode = polling_req || client->irq <= 0;
diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c
index d43aad3..194fe63 100644
--- a/drivers/staging/most/net/net.c
+++ b/drivers/staging/most/net/net.c
@@ -298,7 +298,7 @@ static struct net_dev_context *get_net_dev_hold(struct most_interface *iface)
 
 static int aim_probe_channel(struct most_interface *iface, int channel_idx,
 			     struct most_channel_config *ccfg,
-			     struct kobject *parent, char *name)
+			     char *name)
 {
 	struct net_dev_context *nd;
 	struct net_dev_channel *ch;
@@ -502,7 +502,7 @@ static int aim_rx_data(struct mbo *mbo)
 }
 
 static struct most_aim aim = {
-	.name = "networking",
+	.name = "aim_networking",
 	.probe_channel = aim_probe_channel,
 	.disconnect_channel = aim_disconnect_channel,
 	.tx_completion = aim_resume_tx_channel,
diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c
index 72603ae..4c3397a 100644
--- a/drivers/staging/most/sound/sound.c
+++ b/drivers/staging/most/sound/sound.c
@@ -24,7 +24,7 @@
 #include <linux/kthread.h>
 #include <most/core.h>
 
-#define DRIVER_NAME "sound"
+#define DRIVER_NAME "aim_sound"
 
 static struct list_head dev_list;
 static struct most_aim audio_aim;
@@ -545,7 +545,6 @@ static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw,
  * @iface: pointer to interface instance
  * @channel_id: channel index/ID
  * @cfg: pointer to actual channel configuration
- * @parent: pointer to kobject (needed for sysfs hook-up)
  * @arg_list: string that provides the name of the device to be created in /dev
  *	      plus the desired audio resolution
  *
@@ -555,7 +554,7 @@ static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw,
  */
 static int audio_probe_channel(struct most_interface *iface, int channel_id,
 			       struct most_channel_config *cfg,
-			       struct kobject *parent, char *arg_list)
+			       char *arg_list)
 {
 	struct channel *channel;
 	struct snd_card *card;
diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c
index 2e4f237..9e2a270 100644
--- a/drivers/staging/most/usb/usb.c
+++ b/drivers/staging/most/usb/usb.c
@@ -70,12 +70,12 @@
  * @reg_addr: register address for arbitrary DCI access
  */
 struct most_dci_obj {
-	struct kobject kobj;
+	struct device dev;
 	struct usb_device *usb_device;
 	u16 reg_addr;
 };
 
-#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj)
+#define to_dci_obj(p) container_of(p, struct most_dci_obj, dev)
 
 struct most_dev;
 
@@ -90,7 +90,6 @@ struct clear_hold_work {
 
 /**
  * struct most_dev - holds all usb interface specific stuff
- * @parent: parent object in sysfs
  * @usb_device: pointer to usb device
  * @iface: hardware interface
  * @cap: channel capabilities
@@ -108,7 +107,6 @@ struct clear_hold_work {
  * @poll_work_obj: work for polling link status
  */
 struct most_dev {
-	struct kobject *parent;
 	struct usb_device *usb_device;
 	struct most_interface iface;
 	struct most_channel_capability *cap;
@@ -840,94 +838,6 @@ static void wq_clear_halt(struct work_struct *wq_obj)
 	{ } /* Terminating entry */
 };
 
-#define MOST_DCI_RO_ATTR(_name) \
-	struct most_dci_attribute most_dci_attr_##_name = \
-		__ATTR(_name, 0444, show_value, NULL)
-
-#define MOST_DCI_ATTR(_name) \
-	struct most_dci_attribute most_dci_attr_##_name = \
-		__ATTR(_name, 0644, show_value, store_value)
-
-#define MOST_DCI_WO_ATTR(_name) \
-	struct most_dci_attribute most_dci_attr_##_name = \
-		__ATTR(_name, 0200, NULL, store_value)
-
-/**
- * struct most_dci_attribute - to access the attributes of a dci object
- * @attr: attributes of a dci object
- * @show: pointer to the show function
- * @store: pointer to the store function
- */
-struct most_dci_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct most_dci_obj *d,
-			struct most_dci_attribute *attr,
-			char *buf);
-	ssize_t (*store)(struct most_dci_obj *d,
-			 struct most_dci_attribute *attr,
-			 const char *buf,
-			 size_t count);
-};
-
-#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr)
-
-/**
- * dci_attr_show - show function for dci object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- */
-static ssize_t dci_attr_show(struct kobject *kobj, struct attribute *attr,
-			     char *buf)
-{
-	struct most_dci_attribute *dci_attr = to_dci_attr(attr);
-	struct most_dci_obj *dci_obj = to_dci_obj(kobj);
-
-	if (!dci_attr->show)
-		return -EIO;
-
-	return dci_attr->show(dci_obj, dci_attr, buf);
-}
-
-/**
- * dci_attr_store - store function for dci object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- * @len: length of buffer
- */
-static ssize_t dci_attr_store(struct kobject *kobj,
-			      struct attribute *attr,
-			      const char *buf,
-			      size_t len)
-{
-	struct most_dci_attribute *dci_attr = to_dci_attr(attr);
-	struct most_dci_obj *dci_obj = to_dci_obj(kobj);
-
-	if (!dci_attr->store)
-		return -EIO;
-
-	return dci_attr->store(dci_obj, dci_attr, buf, len);
-}
-
-static const struct sysfs_ops most_dci_sysfs_ops = {
-	.show = dci_attr_show,
-	.store = dci_attr_store,
-};
-
-/**
- * most_dci_release - release function for dci object
- * @kobj: pointer to kobject
- *
- * This frees the memory allocated for the dci object
- */
-static void most_dci_release(struct kobject *kobj)
-{
-	struct most_dci_obj *dci_obj = to_dci_obj(kobj);
-
-	kfree(dci_obj);
-}
-
 struct regs {
 	const char *name;
 	u16 reg;
@@ -968,10 +878,11 @@ static int get_stat_reg_addr(const struct regs *regs, int size,
 #define get_static_reg_addr(regs, name, reg_addr) \
 	get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr)
 
-static ssize_t show_value(struct most_dci_obj *dci_obj,
-			  struct most_dci_attribute *attr, char *buf)
+static ssize_t value_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
 	const char *name = attr->attr.name;
+	struct most_dci_obj *dci_obj = to_dci_obj(dev);
 	u16 val;
 	u16 reg_addr;
 	int err;
@@ -992,13 +903,13 @@ static ssize_t show_value(struct most_dci_obj *dci_obj,
 	return snprintf(buf, PAGE_SIZE, "%04x\n", val);
 }
 
-static ssize_t store_value(struct most_dci_obj *dci_obj,
-			   struct most_dci_attribute *attr,
+static ssize_t value_store(struct device *dev, struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
 	u16 val;
 	u16 reg_addr;
 	const char *name = attr->attr.name;
+	struct most_dci_obj *dci_obj = to_dci_obj(dev);
 	struct usb_device *usb_dev = dci_obj->usb_device;
 	int err = kstrtou16(buf, 16, &val);
 
@@ -1025,86 +936,49 @@ static ssize_t store_value(struct most_dci_obj *dci_obj,
 	return count;
 }
 
-static MOST_DCI_RO_ATTR(ni_state);
-static MOST_DCI_RO_ATTR(packet_bandwidth);
-static MOST_DCI_RO_ATTR(node_address);
-static MOST_DCI_RO_ATTR(node_position);
-static MOST_DCI_WO_ATTR(sync_ep);
-static MOST_DCI_ATTR(mep_filter);
-static MOST_DCI_ATTR(mep_hash0);
-static MOST_DCI_ATTR(mep_hash1);
-static MOST_DCI_ATTR(mep_hash2);
-static MOST_DCI_ATTR(mep_hash3);
-static MOST_DCI_ATTR(mep_eui48_hi);
-static MOST_DCI_ATTR(mep_eui48_mi);
-static MOST_DCI_ATTR(mep_eui48_lo);
-static MOST_DCI_ATTR(arb_address);
-static MOST_DCI_ATTR(arb_value);
-
-/**
- * most_dci_def_attrs - array of default attribute files of the dci object
- */
-static struct attribute *most_dci_def_attrs[] = {
-	&most_dci_attr_ni_state.attr,
-	&most_dci_attr_packet_bandwidth.attr,
-	&most_dci_attr_node_address.attr,
-	&most_dci_attr_node_position.attr,
-	&most_dci_attr_sync_ep.attr,
-	&most_dci_attr_mep_filter.attr,
-	&most_dci_attr_mep_hash0.attr,
-	&most_dci_attr_mep_hash1.attr,
-	&most_dci_attr_mep_hash2.attr,
-	&most_dci_attr_mep_hash3.attr,
-	&most_dci_attr_mep_eui48_hi.attr,
-	&most_dci_attr_mep_eui48_mi.attr,
-	&most_dci_attr_mep_eui48_lo.attr,
-	&most_dci_attr_arb_address.attr,
-	&most_dci_attr_arb_value.attr,
+DEVICE_ATTR(ni_state, 0444, value_show, NULL);
+DEVICE_ATTR(packet_bandwidth, 0444, value_show, NULL);
+DEVICE_ATTR(node_address, 0444, value_show, NULL);
+DEVICE_ATTR(node_position, 0444, value_show, NULL);
+DEVICE_ATTR(sync_ep, 0200, NULL, value_store);
+DEVICE_ATTR(mep_filter, 0644, value_show, value_store);
+DEVICE_ATTR(mep_hash0, 0644, value_show, value_store);
+DEVICE_ATTR(mep_hash1, 0644, value_show, value_store);
+DEVICE_ATTR(mep_hash2, 0644, value_show, value_store);
+DEVICE_ATTR(mep_hash3, 0644, value_show, value_store);
+DEVICE_ATTR(mep_eui48_hi, 0644, value_show, value_store);
+DEVICE_ATTR(mep_eui48_mi, 0644, value_show, value_store);
+DEVICE_ATTR(mep_eui48_lo, 0644, value_show, value_store);
+DEVICE_ATTR(arb_address, 0644, value_show, value_store);
+DEVICE_ATTR(arb_value, 0644, value_show, value_store);
+
+static struct attribute *dci_attrs[] = {
+	&dev_attr_ni_state.attr,
+	&dev_attr_packet_bandwidth.attr,
+	&dev_attr_node_address.attr,
+	&dev_attr_node_position.attr,
+	&dev_attr_sync_ep.attr,
+	&dev_attr_mep_filter.attr,
+	&dev_attr_mep_hash0.attr,
+	&dev_attr_mep_hash1.attr,
+	&dev_attr_mep_hash2.attr,
+	&dev_attr_mep_hash3.attr,
+	&dev_attr_mep_eui48_hi.attr,
+	&dev_attr_mep_eui48_mi.attr,
+	&dev_attr_mep_eui48_lo.attr,
+	&dev_attr_arb_address.attr,
+	&dev_attr_arb_value.attr,
 	NULL,
 };
 
-/**
- * DCI ktype
- */
-static struct kobj_type most_dci_ktype = {
-	.sysfs_ops = &most_dci_sysfs_ops,
-	.release = most_dci_release,
-	.default_attrs = most_dci_def_attrs,
+static struct attribute_group dci_attr_group = {
+	.attrs = dci_attrs,
 };
 
-/**
- * create_most_dci_obj - allocates a dci object
- * @parent: parent kobject
- *
- * This creates a dci object and registers it with sysfs.
- * Returns a pointer to the object or NULL when something went wrong.
- */
-static struct
-most_dci_obj *create_most_dci_obj(struct kobject *parent)
-{
-	struct most_dci_obj *most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL);
-	int retval;
-
-	if (!most_dci)
-		return NULL;
-
-	retval = kobject_init_and_add(&most_dci->kobj, &most_dci_ktype, parent,
-				      "dci");
-	if (retval) {
-		kobject_put(&most_dci->kobj);
-		return NULL;
-	}
-	return most_dci;
-}
-
-/**
- * destroy_most_dci_obj - DCI object release function
- * @p: pointer to dci object
- */
-static void destroy_most_dci_obj(struct most_dci_obj *p)
-{
-	kobject_put(&p->kobj);
-}
+static const struct attribute_group *dci_attr_groups[] = {
+	&dci_attr_group,
+	NULL,
+};
 
 /**
  * hdm_probe - probe function of USB device driver
@@ -1218,33 +1092,36 @@ static void destroy_most_dci_obj(struct most_dci_obj *p)
 		   usb_dev->config->desc.bConfigurationValue,
 		   usb_iface_desc->desc.bInterfaceNumber);
 
-	mdev->parent = most_register_interface(&mdev->iface);
-	if (IS_ERR(mdev->parent)) {
-		ret = PTR_ERR(mdev->parent);
+	ret = most_register_interface(&mdev->iface);
+	if (ret)
 		goto exit_free4;
-	}
 
 	mutex_lock(&mdev->io_mutex);
 	if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 ||
 	    le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 ||
 	    le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) {
-		/* this increments the reference count of the instance
-		 * object of the core
-		 */
-		mdev->dci = create_most_dci_obj(mdev->parent);
+		mdev->dci = kzalloc(sizeof(*mdev->dci), GFP_KERNEL);
 		if (!mdev->dci) {
 			mutex_unlock(&mdev->io_mutex);
 			most_deregister_interface(&mdev->iface);
 			ret = -ENOMEM;
 			goto exit_free4;
 		}
-
-		kobject_uevent(&mdev->dci->kobj, KOBJ_ADD);
+		mdev->dci->dev.init_name = "dci";
+		mdev->dci->dev.parent = &mdev->iface.dev;
+		mdev->dci->dev.groups = dci_attr_groups;
+		if (device_register(&mdev->dci->dev)) {
+			mutex_unlock(&mdev->io_mutex);
+			most_deregister_interface(&mdev->iface);
+			ret = -ENOMEM;
+			goto exit_free5;
+		}
 		mdev->dci->usb_device = mdev->usb_device;
 	}
 	mutex_unlock(&mdev->io_mutex);
 	return 0;
-
+exit_free5:
+	kfree(mdev->dci);
 exit_free4:
 	kfree(mdev->busy_urbs);
 exit_free3:
@@ -1284,7 +1161,8 @@ static void hdm_disconnect(struct usb_interface *interface)
 	del_timer_sync(&mdev->link_stat_timer);
 	cancel_work_sync(&mdev->poll_work_obj);
 
-	destroy_most_dci_obj(mdev->dci);
+	device_unregister(&mdev->dci->dev);
+	kfree(mdev->dci);
 	most_deregister_interface(&mdev->iface);
 
 	kfree(mdev->busy_urbs);
diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c
index eed9046..5b704d9 100644
--- a/drivers/staging/most/video/video.c
+++ b/drivers/staging/most/video/video.c
@@ -487,7 +487,7 @@ static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev)
 
 static int aim_probe_channel(struct most_interface *iface, int channel_idx,
 			     struct most_channel_config *ccfg,
-			     struct kobject *parent, char *name)
+			     char *name)
 {
 	int ret;
 	struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
@@ -570,7 +570,7 @@ static int aim_disconnect_channel(struct most_interface *iface,
 }
 
 static struct most_aim aim_info = {
-	.name = "v4l",
+	.name = "aim_v4l",
 	.probe_channel = aim_probe_channel,
 	.disconnect_channel = aim_disconnect_channel,
 	.rx_completion = aim_rx_data,
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 03/26] staging: most: core: rename structure
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 02/26] staging: most: integrate driver in kernel's device model Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 04/26] staging: most: core: rename struct most_c_aim_obj to pipe Christian Gromm
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch renames the structure most_c_obj to most_channel. This is done
to enhance readability.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 100 ++++++++++++++++++++++----------------------
 1 file changed, 50 insertions(+), 50 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 54a56a0..2abd0a1 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -43,7 +43,7 @@ struct most_c_aim_obj {
 	int num_buffers;
 };
 
-struct most_c_obj {
+struct most_channel {
 	struct device dev;
 	struct completion cleanup;
 	atomic_t mbo_ref;
@@ -69,13 +69,13 @@ struct most_c_obj {
 	wait_queue_head_t hdm_fifo_wq;
 };
 
-#define to_c_obj(d) container_of(d, struct most_c_obj, dev)
+#define to_channel(d) container_of(d, struct most_channel, dev)
 
 struct most_inst_obj {
 	int dev_id;
 	struct most_interface *iface;
 	struct list_head channel_list;
-	struct most_c_obj *channel[MAX_CHANNELS];
+	struct most_channel *channel[MAX_CHANNELS];
 	struct list_head list;
 };
 
@@ -130,7 +130,7 @@ int most_match(struct device *dev, struct device_driver *drv)
  */
 static void most_free_mbo_coherent(struct mbo *mbo)
 {
-	struct most_c_obj *c = mbo->context;
+	struct most_channel *c = mbo->context;
 	u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
 
 	dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address,
@@ -144,7 +144,7 @@ static void most_free_mbo_coherent(struct mbo *mbo)
  * flush_channel_fifos - clear the channel fifos
  * @c: pointer to channel object
  */
-static void flush_channel_fifos(struct most_c_obj *c)
+static void flush_channel_fifos(struct most_channel *c)
 {
 	unsigned long flags, hf_flags;
 	struct mbo *mbo, *tmp;
@@ -178,7 +178,7 @@ static void flush_channel_fifos(struct most_c_obj *c)
  * flush_trash_fifo - clear the trash fifo
  * @c: pointer to channel object
  */
-static int flush_trash_fifo(struct most_c_obj *c)
+static int flush_trash_fifo(struct most_channel *c)
 {
 	struct mbo *mbo, *tmp;
 	unsigned long flags;
@@ -198,7 +198,7 @@ static ssize_t available_directions_show(struct device *dev,
 					 struct device_attribute *attr,
 					 char *buf)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 	unsigned int i = c->channel_id;
 
 	strcpy(buf, "");
@@ -214,7 +214,7 @@ static ssize_t available_datatypes_show(struct device *dev,
 					struct device_attribute *attr,
 					char *buf)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 	unsigned int i = c->channel_id;
 
 	strcpy(buf, "");
@@ -234,7 +234,7 @@ static ssize_t number_of_packet_buffers_show(struct device *dev,
 					     struct device_attribute *attr,
 					     char *buf)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 	unsigned int i = c->channel_id;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
@@ -245,7 +245,7 @@ static ssize_t number_of_stream_buffers_show(struct device *dev,
 					     struct device_attribute *attr,
 					     char *buf)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 	unsigned int i = c->channel_id;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
@@ -256,7 +256,7 @@ static ssize_t size_of_packet_buffer_show(struct device *dev,
 					  struct device_attribute *attr,
 					  char *buf)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 	unsigned int i = c->channel_id;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
@@ -267,7 +267,7 @@ static ssize_t size_of_stream_buffer_show(struct device *dev,
 					  struct device_attribute *attr,
 					  char *buf)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 	unsigned int i = c->channel_id;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
@@ -278,7 +278,7 @@ static ssize_t channel_starving_show(struct device *dev,
 				     struct device_attribute *attr,
 				     char *buf)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving);
 }
@@ -287,7 +287,7 @@ static ssize_t set_number_of_buffers_show(struct device *dev,
 					  struct device_attribute *attr,
 					  char *buf)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers);
 }
@@ -297,7 +297,7 @@ static ssize_t set_number_of_buffers_store(struct device *dev,
 					   const char *buf,
 					   size_t count)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 
 	int ret = kstrtou16(buf, 0, &c->cfg.num_buffers);
 
@@ -310,7 +310,7 @@ static ssize_t set_buffer_size_show(struct device *dev,
 				    struct device_attribute *attr,
 				    char *buf)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size);
 }
@@ -320,7 +320,7 @@ static ssize_t set_buffer_size_store(struct device *dev,
 				     const char *buf,
 				     size_t count)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 
 	int ret = kstrtou16(buf, 0, &c->cfg.buffer_size);
 
@@ -333,7 +333,7 @@ static ssize_t set_direction_show(struct device *dev,
 				  struct device_attribute *attr,
 				  char *buf)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 
 	if (c->cfg.direction & MOST_CH_TX)
 		return snprintf(buf, PAGE_SIZE, "tx\n");
@@ -347,7 +347,7 @@ static ssize_t set_direction_store(struct device *dev,
 				   const char *buf,
 				   size_t count)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 
 	if (!strcmp(buf, "dir_rx\n")) {
 		c->cfg.direction = MOST_CH_RX;
@@ -369,7 +369,7 @@ static ssize_t set_datatype_show(struct device *dev,
 				 char *buf)
 {
 	int i;
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 
 	for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
 		if (c->cfg.data_type & ch_data_type[i].most_ch_data_type)
@@ -384,7 +384,7 @@ static ssize_t set_datatype_store(struct device *dev,
 				  size_t count)
 {
 	int i;
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 
 	for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
 		if (!strcmp(buf, ch_data_type[i].name)) {
@@ -404,7 +404,7 @@ static ssize_t set_subbuffer_size_show(struct device *dev,
 				       struct device_attribute *attr,
 				       char *buf)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size);
 }
@@ -414,7 +414,7 @@ static ssize_t set_subbuffer_size_store(struct device *dev,
 					const char *buf,
 					size_t count)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 
 	int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size);
 
@@ -427,7 +427,7 @@ static ssize_t set_packets_per_xact_show(struct device *dev,
 					 struct device_attribute *attr,
 					 char *buf)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact);
 }
@@ -437,7 +437,7 @@ static ssize_t set_packets_per_xact_store(struct device *dev,
 					  const char *buf,
 					  size_t count)
 {
-	struct most_c_obj *c = to_c_obj(dev);
+	struct most_channel *c = to_channel(dev);
 
 	int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact);
 
@@ -559,7 +559,7 @@ static ssize_t interface_show(struct device *dev,
 static ssize_t links_show(struct device *dev, struct device_attribute *attr,
 			  char *buf)
 {
-	struct most_c_obj *c;
+	struct most_channel *c;
 	struct most_inst_obj *i;
 	struct most_aim *aim = to_most_aim(dev);
 	int offs = 0;
@@ -623,9 +623,9 @@ static int split_string(char *buf, char **a, char **b, char **c)
  *
  * This retrieves the pointer to a channel object.
  */
-static struct most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
+static struct most_channel *get_channel_by_name(char *mdev, char *mdev_ch)
 {
-	struct most_c_obj *c, *tmp;
+	struct most_channel *c, *tmp;
 	struct most_inst_obj *i, *i_tmp;
 	int found = 0;
 
@@ -649,7 +649,7 @@ static struct most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
 	return c;
 }
 
-static int link_channel_to_aim(struct most_c_obj *c, struct most_aim *aim,
+static int link_channel_to_aim(struct most_channel *c, struct most_aim *aim,
 			       char *aim_param)
 {
 	int ret;
@@ -700,7 +700,7 @@ static ssize_t add_link_store(struct device *dev,
 			      const char *buf,
 			      size_t len)
 {
-	struct most_c_obj *c;
+	struct most_channel *c;
 	struct most_aim *aim = to_most_aim(dev);
 	char buffer[STRING_SIZE];
 	char *mdev;
@@ -748,7 +748,7 @@ static ssize_t remove_link_store(struct device *dev,
 				 const char *buf,
 				 size_t len)
 {
-	struct most_c_obj *c;
+	struct most_channel *c;
 	struct most_aim *aim = to_most_aim(dev);
 	char buffer[STRING_SIZE];
 	char *mdev;
@@ -800,14 +800,14 @@ static ssize_t remove_link_store(struct device *dev,
 static inline void trash_mbo(struct mbo *mbo)
 {
 	unsigned long flags;
-	struct most_c_obj *c = mbo->context;
+	struct most_channel *c = mbo->context;
 
 	spin_lock_irqsave(&c->fifo_lock, flags);
 	list_add(&mbo->list, &c->trash_fifo);
 	spin_unlock_irqrestore(&c->fifo_lock, flags);
 }
 
-static bool hdm_mbo_ready(struct most_c_obj *c)
+static bool hdm_mbo_ready(struct most_channel *c)
 {
 	bool empty;
 
@@ -824,7 +824,7 @@ static bool hdm_mbo_ready(struct most_c_obj *c)
 static void nq_hdm_mbo(struct mbo *mbo)
 {
 	unsigned long flags;
-	struct most_c_obj *c = mbo->context;
+	struct most_channel *c = mbo->context;
 
 	spin_lock_irqsave(&c->fifo_lock, flags);
 	list_add_tail(&mbo->list, &c->halt_fifo);
@@ -834,7 +834,7 @@ static void nq_hdm_mbo(struct mbo *mbo)
 
 static int hdm_enqueue_thread(void *data)
 {
-	struct most_c_obj *c = data;
+	struct most_channel *c = data;
 	struct mbo *mbo;
 	int ret;
 	typeof(c->iface->enqueue) enqueue = c->iface->enqueue;
@@ -872,7 +872,7 @@ static int hdm_enqueue_thread(void *data)
 	return 0;
 }
 
-static int run_enqueue_thread(struct most_c_obj *c, int channel_id)
+static int run_enqueue_thread(struct most_channel *c, int channel_id)
 {
 	struct task_struct *task =
 		kthread_run(hdm_enqueue_thread, c, "hdm_fifo_%d",
@@ -899,7 +899,7 @@ static int run_enqueue_thread(struct most_c_obj *c, int channel_id)
 static void arm_mbo(struct mbo *mbo)
 {
 	unsigned long flags;
-	struct most_c_obj *c;
+	struct most_channel *c;
 
 	BUG_ON((!mbo) || (!mbo->context));
 	c = mbo->context;
@@ -934,7 +934,7 @@ static void arm_mbo(struct mbo *mbo)
  *
  * Returns the number of allocated and enqueued MBOs.
  */
-static int arm_mbo_chain(struct most_c_obj *c, int dir,
+static int arm_mbo_chain(struct most_channel *c, int dir,
 			 void (*compl)(struct mbo *))
 {
 	unsigned int i;
@@ -1002,7 +1002,7 @@ void most_submit_mbo(struct mbo *mbo)
  */
 static void most_write_completion(struct mbo *mbo)
 {
-	struct most_c_obj *c;
+	struct most_channel *c;
 
 	BUG_ON((!mbo) || (!mbo->context));
 
@@ -1018,7 +1018,7 @@ static void most_write_completion(struct mbo *mbo)
 int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim)
 {
 	struct most_inst_obj *inst = iface->priv;
-	struct most_c_obj *c = inst->channel[id];
+	struct most_channel *c = inst->channel[id];
 	unsigned long flags;
 	int empty;
 
@@ -1049,7 +1049,7 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id,
 			 struct most_aim *aim)
 {
 	struct mbo *mbo;
-	struct most_c_obj *c;
+	struct most_channel *c;
 	struct most_inst_obj *inst = iface->priv;
 	unsigned long flags;
 	int *num_buffers_ptr;
@@ -1091,7 +1091,7 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id,
  */
 void most_put_mbo(struct mbo *mbo)
 {
-	struct most_c_obj *c = mbo->context;
+	struct most_channel *c = mbo->context;
 
 	if (c->cfg.direction == MOST_CH_TX) {
 		arm_mbo(mbo);
@@ -1114,7 +1114,7 @@ void most_put_mbo(struct mbo *mbo)
  */
 static void most_read_completion(struct mbo *mbo)
 {
-	struct most_c_obj *c = mbo->context;
+	struct most_channel *c = mbo->context;
 
 	if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) {
 		trash_mbo(mbo);
@@ -1157,7 +1157,7 @@ int most_start_channel(struct most_interface *iface, int id,
 	int num_buffer;
 	int ret;
 	struct most_inst_obj *inst = iface->priv;
-	struct most_c_obj *c = inst->channel[id];
+	struct most_channel *c = inst->channel[id];
 
 	if (unlikely(!c))
 		return -EINVAL;
@@ -1226,7 +1226,7 @@ int most_stop_channel(struct most_interface *iface, int id,
 		      struct most_aim *aim)
 {
 	struct most_inst_obj *inst;
-	struct most_c_obj *c;
+	struct most_channel *c;
 
 	if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) {
 		pr_err("Bad interface or index out of range\n");
@@ -1317,7 +1317,7 @@ int most_register_aim(struct most_aim *aim)
  */
 int most_deregister_aim(struct most_aim *aim)
 {
-	struct most_c_obj *c, *tmp;
+	struct most_channel *c, *tmp;
 	struct most_inst_obj *i, *i_tmp;
 
 	if (!aim) {
@@ -1365,7 +1365,7 @@ int most_register_interface(struct most_interface *iface)
 	int id;
 	char name[STRING_SIZE];
 	char channel_name[STRING_SIZE];
-	struct most_c_obj *c;
+	struct most_channel *c;
 	struct most_inst_obj *inst;
 
 	if (!iface || !iface->enqueue || !iface->configure ||
@@ -1472,7 +1472,7 @@ int most_register_interface(struct most_interface *iface)
 void most_deregister_interface(struct most_interface *iface)
 {
 	int i;
-	struct most_c_obj *c;
+	struct most_channel *c;
 	struct most_inst_obj *inst;
 
 	pr_info("deregistering MOST device %s (%s)\n", dev_name(&iface->dev), iface->description);
@@ -1511,7 +1511,7 @@ void most_deregister_interface(struct most_interface *iface)
 void most_stop_enqueue(struct most_interface *iface, int id)
 {
 	struct most_inst_obj *inst = iface->priv;
-	struct most_c_obj *c = inst->channel[id];
+	struct most_channel *c = inst->channel[id];
 
 	if (!c)
 		return;
@@ -1533,7 +1533,7 @@ void most_stop_enqueue(struct most_interface *iface, int id)
 void most_resume_enqueue(struct most_interface *iface, int id)
 {
 	struct most_inst_obj *inst = iface->priv;
-	struct most_c_obj *c = inst->channel[id];
+	struct most_channel *c = inst->channel[id];
 
 	if (!c)
 		return;
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 04/26] staging: most: core: rename struct most_c_aim_obj to pipe
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 02/26] staging: most: integrate driver in kernel's device model Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 03/26] staging: most: core: rename structure Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 05/26] staging: most: core: rename struct memeber Christian Gromm
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch replaces the confusing name of struct "most_c_aim_obj"
with "pipe" to better express the function that is behind the
structure.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 2abd0a1..35fedd5 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -37,7 +37,7 @@
 static struct ida mdev_id;
 static int dummy_num_buffers;
 
-struct most_c_aim_obj {
+struct pipe {
 	struct most_aim *ptr;
 	int refs;
 	int num_buffers;
@@ -62,8 +62,8 @@ struct most_channel {
 	spinlock_t fifo_lock;
 	struct list_head halt_fifo;
 	struct list_head list;
-	struct most_c_aim_obj aim0;
-	struct most_c_aim_obj aim1;
+	struct pipe aim0;
+	struct pipe aim1;
 	struct list_head trash_fifo;
 	struct task_struct *hdm_enqueue_task;
 	wait_queue_head_t hdm_fifo_wq;
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 05/26] staging: most: core: rename struct memeber
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (2 preceding siblings ...)
  2017-10-13 14:32 ` [PATCH v2 04/26] staging: most: core: rename struct most_c_aim_obj to pipe Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 06/26] staging: most: core: rename members aim* of struct most_channel Christian Gromm
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch renames the member "ptr" of struct pipe to "aim". This is
needed to increase the readability of the code.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 78 ++++++++++++++++++++++-----------------------
 1 file changed, 39 insertions(+), 39 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 35fedd5..a3d60b3 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -38,7 +38,7 @@
 static int dummy_num_buffers;
 
 struct pipe {
-	struct most_aim *ptr;
+	struct most_aim *aim;
 	int refs;
 	int num_buffers;
 };
@@ -566,7 +566,7 @@ static ssize_t links_show(struct device *dev, struct device_attribute *attr,
 
 	list_for_each_entry(i, &instance_list, list) {
 		list_for_each_entry(c, &i->channel_list, list) {
-			if (c->aim0.ptr == aim || c->aim1.ptr == aim) {
+			if (c->aim0.aim == aim || c->aim1.aim == aim) {
 				offs += snprintf(buf + offs, PAGE_SIZE - offs,
 						 "%s:%s\n",
 						 dev_name(&i->iface->dev),
@@ -655,10 +655,10 @@ static int link_channel_to_aim(struct most_channel *c, struct most_aim *aim,
 	int ret;
 	struct most_aim **aim_ptr;
 
-	if (!c->aim0.ptr)
-		aim_ptr = &c->aim0.ptr;
-	else if (!c->aim1.ptr)
-		aim_ptr = &c->aim1.ptr;
+	if (!c->aim0.aim)
+		aim_ptr = &c->aim0.aim;
+	else if (!c->aim1.aim)
+		aim_ptr = &c->aim1.aim;
 	else
 		return -ENOSPC;
 
@@ -767,10 +767,10 @@ static ssize_t remove_link_store(struct device *dev,
 
 	if (aim->disconnect_channel(c->iface, c->channel_id))
 		return -EIO;
-	if (c->aim0.ptr == aim)
-		c->aim0.ptr = NULL;
-	if (c->aim1.ptr == aim)
-		c->aim1.ptr = NULL;
+	if (c->aim0.aim == aim)
+		c->aim0.aim = NULL;
+	if (c->aim1.aim == aim)
+		c->aim1.aim = NULL;
 	return len;
 }
 
@@ -914,11 +914,11 @@ static void arm_mbo(struct mbo *mbo)
 	list_add_tail(&mbo->list, &c->fifo);
 	spin_unlock_irqrestore(&c->fifo_lock, flags);
 
-	if (c->aim0.refs && c->aim0.ptr->tx_completion)
-		c->aim0.ptr->tx_completion(c->iface, c->channel_id);
+	if (c->aim0.refs && c->aim0.aim->tx_completion)
+		c->aim0.aim->tx_completion(c->iface, c->channel_id);
 
-	if (c->aim1.refs && c->aim1.ptr->tx_completion)
-		c->aim1.ptr->tx_completion(c->iface, c->channel_id);
+	if (c->aim1.refs && c->aim1.aim->tx_completion)
+		c->aim1.aim->tx_completion(c->iface, c->channel_id);
 }
 
 /**
@@ -1026,8 +1026,8 @@ int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim)
 		return -EINVAL;
 
 	if (c->aim0.refs && c->aim1.refs &&
-	    ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) ||
-	     (aim == c->aim1.ptr && c->aim1.num_buffers <= 0)))
+	    ((aim == c->aim0.aim && c->aim0.num_buffers <= 0) ||
+	     (aim == c->aim1.aim && c->aim1.num_buffers <= 0)))
 		return 0;
 
 	spin_lock_irqsave(&c->fifo_lock, flags);
@@ -1059,13 +1059,13 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id,
 		return NULL;
 
 	if (c->aim0.refs && c->aim1.refs &&
-	    ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) ||
-	     (aim == c->aim1.ptr && c->aim1.num_buffers <= 0)))
+	    ((aim == c->aim0.aim && c->aim0.num_buffers <= 0) ||
+	     (aim == c->aim1.aim && c->aim1.num_buffers <= 0)))
 		return NULL;
 
-	if (aim == c->aim0.ptr)
+	if (aim == c->aim0.aim)
 		num_buffers_ptr = &c->aim0.num_buffers;
-	else if (aim == c->aim1.ptr)
+	else if (aim == c->aim1.aim)
 		num_buffers_ptr = &c->aim1.num_buffers;
 	else
 		num_buffers_ptr = &dummy_num_buffers;
@@ -1130,12 +1130,12 @@ static void most_read_completion(struct mbo *mbo)
 	if (atomic_sub_and_test(1, &c->mbo_nq_level))
 		c->is_starving = 1;
 
-	if (c->aim0.refs && c->aim0.ptr->rx_completion &&
-	    c->aim0.ptr->rx_completion(mbo) == 0)
+	if (c->aim0.refs && c->aim0.aim->rx_completion &&
+	    c->aim0.aim->rx_completion(mbo) == 0)
 		return;
 
-	if (c->aim1.refs && c->aim1.ptr->rx_completion &&
-	    c->aim1.ptr->rx_completion(mbo) == 0)
+	if (c->aim1.refs && c->aim1.aim->rx_completion &&
+	    c->aim1.aim->rx_completion(mbo) == 0)
 		return;
 
 	most_put_mbo(mbo);
@@ -1203,9 +1203,9 @@ int most_start_channel(struct most_interface *iface, int id,
 	atomic_set(&c->mbo_ref, num_buffer);
 
 out:
-	if (aim == c->aim0.ptr)
+	if (aim == c->aim0.aim)
 		c->aim0.refs++;
-	if (aim == c->aim1.ptr)
+	if (aim == c->aim1.aim)
 		c->aim1.refs++;
 	mutex_unlock(&c->start_mutex);
 	return 0;
@@ -1270,9 +1270,9 @@ int most_stop_channel(struct most_interface *iface, int id,
 	c->is_poisoned = false;
 
 out:
-	if (aim == c->aim0.ptr)
+	if (aim == c->aim0.aim)
 		c->aim0.refs--;
-	if (aim == c->aim1.ptr)
+	if (aim == c->aim1.aim)
 		c->aim1.refs--;
 	mutex_unlock(&c->start_mutex);
 	return 0;
@@ -1327,13 +1327,13 @@ int most_deregister_aim(struct most_aim *aim)
 
 	list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
 		list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
-			if (c->aim0.ptr == aim || c->aim1.ptr == aim)
+			if (c->aim0.aim == aim || c->aim1.aim == aim)
 				aim->disconnect_channel(
 					c->iface, c->channel_id);
-			if (c->aim0.ptr == aim)
-				c->aim0.ptr = NULL;
-			if (c->aim1.ptr == aim)
-				c->aim1.ptr = NULL;
+			if (c->aim0.aim == aim)
+				c->aim0.aim = NULL;
+			if (c->aim1.aim == aim)
+				c->aim1.aim = NULL;
 		}
 	}
 	device_unregister(&aim->dev);
@@ -1479,14 +1479,14 @@ void most_deregister_interface(struct most_interface *iface)
 	inst = iface->priv;
 	for (i = 0; i < iface->num_channels; i++) {
 		c = inst->channel[i];
-		if (c->aim0.ptr)
-			c->aim0.ptr->disconnect_channel(c->iface,
+		if (c->aim0.aim)
+			c->aim0.aim->disconnect_channel(c->iface,
 							c->channel_id);
-		if (c->aim1.ptr)
-			c->aim1.ptr->disconnect_channel(c->iface,
+		if (c->aim1.aim)
+			c->aim1.aim->disconnect_channel(c->iface,
 							c->channel_id);
-		c->aim0.ptr = NULL;
-		c->aim1.ptr = NULL;
+		c->aim0.aim = NULL;
+		c->aim1.aim = NULL;
 		list_del(&c->list);
 		device_unregister(&c->dev);
 		kfree(c);
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 06/26] staging: most: core: rename members aim* of struct most_channel
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (3 preceding siblings ...)
  2017-10-13 14:32 ` [PATCH v2 05/26] staging: most: core: rename struct memeber Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 07/26] staging: most: core: use structure to pack driver specific data Christian Gromm
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch renames the struct members "aim0" and "aim0" to "pipe0" and "pipe1".

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 104 ++++++++++++++++++++++----------------------
 1 file changed, 52 insertions(+), 52 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index a3d60b3..9d37ace 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -62,8 +62,8 @@ struct most_channel {
 	spinlock_t fifo_lock;
 	struct list_head halt_fifo;
 	struct list_head list;
-	struct pipe aim0;
-	struct pipe aim1;
+	struct pipe pipe0;
+	struct pipe pipe1;
 	struct list_head trash_fifo;
 	struct task_struct *hdm_enqueue_task;
 	wait_queue_head_t hdm_fifo_wq;
@@ -566,7 +566,7 @@ static ssize_t links_show(struct device *dev, struct device_attribute *attr,
 
 	list_for_each_entry(i, &instance_list, list) {
 		list_for_each_entry(c, &i->channel_list, list) {
-			if (c->aim0.aim == aim || c->aim1.aim == aim) {
+			if (c->pipe0.aim == aim || c->pipe1.aim == aim) {
 				offs += snprintf(buf + offs, PAGE_SIZE - offs,
 						 "%s:%s\n",
 						 dev_name(&i->iface->dev),
@@ -655,10 +655,10 @@ static int link_channel_to_aim(struct most_channel *c, struct most_aim *aim,
 	int ret;
 	struct most_aim **aim_ptr;
 
-	if (!c->aim0.aim)
-		aim_ptr = &c->aim0.aim;
-	else if (!c->aim1.aim)
-		aim_ptr = &c->aim1.aim;
+	if (!c->pipe0.aim)
+		aim_ptr = &c->pipe0.aim;
+	else if (!c->pipe1.aim)
+		aim_ptr = &c->pipe1.aim;
 	else
 		return -ENOSPC;
 
@@ -767,10 +767,10 @@ static ssize_t remove_link_store(struct device *dev,
 
 	if (aim->disconnect_channel(c->iface, c->channel_id))
 		return -EIO;
-	if (c->aim0.aim == aim)
-		c->aim0.aim = NULL;
-	if (c->aim1.aim == aim)
-		c->aim1.aim = NULL;
+	if (c->pipe0.aim == aim)
+		c->pipe0.aim = NULL;
+	if (c->pipe1.aim == aim)
+		c->pipe1.aim = NULL;
 	return len;
 }
 
@@ -914,11 +914,11 @@ static void arm_mbo(struct mbo *mbo)
 	list_add_tail(&mbo->list, &c->fifo);
 	spin_unlock_irqrestore(&c->fifo_lock, flags);
 
-	if (c->aim0.refs && c->aim0.aim->tx_completion)
-		c->aim0.aim->tx_completion(c->iface, c->channel_id);
+	if (c->pipe0.refs && c->pipe0.aim->tx_completion)
+		c->pipe0.aim->tx_completion(c->iface, c->channel_id);
 
-	if (c->aim1.refs && c->aim1.aim->tx_completion)
-		c->aim1.aim->tx_completion(c->iface, c->channel_id);
+	if (c->pipe1.refs && c->pipe1.aim->tx_completion)
+		c->pipe1.aim->tx_completion(c->iface, c->channel_id);
 }
 
 /**
@@ -1025,9 +1025,9 @@ int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim)
 	if (unlikely(!c))
 		return -EINVAL;
 
-	if (c->aim0.refs && c->aim1.refs &&
-	    ((aim == c->aim0.aim && c->aim0.num_buffers <= 0) ||
-	     (aim == c->aim1.aim && c->aim1.num_buffers <= 0)))
+	if (c->pipe0.refs && c->pipe1.refs &&
+	    ((aim == c->pipe0.aim && c->pipe0.num_buffers <= 0) ||
+	     (aim == c->pipe1.aim && c->pipe1.num_buffers <= 0)))
 		return 0;
 
 	spin_lock_irqsave(&c->fifo_lock, flags);
@@ -1058,15 +1058,15 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id,
 	if (unlikely(!c))
 		return NULL;
 
-	if (c->aim0.refs && c->aim1.refs &&
-	    ((aim == c->aim0.aim && c->aim0.num_buffers <= 0) ||
-	     (aim == c->aim1.aim && c->aim1.num_buffers <= 0)))
+	if (c->pipe0.refs && c->pipe1.refs &&
+	    ((aim == c->pipe0.aim && c->pipe0.num_buffers <= 0) ||
+	     (aim == c->pipe1.aim && c->pipe1.num_buffers <= 0)))
 		return NULL;
 
-	if (aim == c->aim0.aim)
-		num_buffers_ptr = &c->aim0.num_buffers;
-	else if (aim == c->aim1.aim)
-		num_buffers_ptr = &c->aim1.num_buffers;
+	if (aim == c->pipe0.aim)
+		num_buffers_ptr = &c->pipe0.num_buffers;
+	else if (aim == c->pipe1.aim)
+		num_buffers_ptr = &c->pipe1.num_buffers;
 	else
 		num_buffers_ptr = &dummy_num_buffers;
 
@@ -1130,12 +1130,12 @@ static void most_read_completion(struct mbo *mbo)
 	if (atomic_sub_and_test(1, &c->mbo_nq_level))
 		c->is_starving = 1;
 
-	if (c->aim0.refs && c->aim0.aim->rx_completion &&
-	    c->aim0.aim->rx_completion(mbo) == 0)
+	if (c->pipe0.refs && c->pipe0.aim->rx_completion &&
+	    c->pipe0.aim->rx_completion(mbo) == 0)
 		return;
 
-	if (c->aim1.refs && c->aim1.aim->rx_completion &&
-	    c->aim1.aim->rx_completion(mbo) == 0)
+	if (c->pipe1.refs && c->pipe1.aim->rx_completion &&
+	    c->pipe1.aim->rx_completion(mbo) == 0)
 		return;
 
 	most_put_mbo(mbo);
@@ -1163,7 +1163,7 @@ int most_start_channel(struct most_interface *iface, int id,
 		return -EINVAL;
 
 	mutex_lock(&c->start_mutex);
-	if (c->aim0.refs + c->aim1.refs > 0)
+	if (c->pipe0.refs + c->pipe1.refs > 0)
 		goto out; /* already started by other aim */
 
 	if (!try_module_get(iface->mod)) {
@@ -1198,15 +1198,15 @@ int most_start_channel(struct most_interface *iface, int id,
 		goto error;
 
 	c->is_starving = 0;
-	c->aim0.num_buffers = c->cfg.num_buffers / 2;
-	c->aim1.num_buffers = c->cfg.num_buffers - c->aim0.num_buffers;
+	c->pipe0.num_buffers = c->cfg.num_buffers / 2;
+	c->pipe1.num_buffers = c->cfg.num_buffers - c->pipe0.num_buffers;
 	atomic_set(&c->mbo_ref, num_buffer);
 
 out:
-	if (aim == c->aim0.aim)
-		c->aim0.refs++;
-	if (aim == c->aim1.aim)
-		c->aim1.refs++;
+	if (aim == c->pipe0.aim)
+		c->pipe0.refs++;
+	if (aim == c->pipe1.aim)
+		c->pipe1.refs++;
 	mutex_unlock(&c->start_mutex);
 	return 0;
 
@@ -1238,7 +1238,7 @@ int most_stop_channel(struct most_interface *iface, int id,
 		return -EINVAL;
 
 	mutex_lock(&c->start_mutex);
-	if (c->aim0.refs + c->aim1.refs >= 2)
+	if (c->pipe0.refs + c->pipe1.refs >= 2)
 		goto out;
 
 	if (c->hdm_enqueue_task)
@@ -1270,10 +1270,10 @@ int most_stop_channel(struct most_interface *iface, int id,
 	c->is_poisoned = false;
 
 out:
-	if (aim == c->aim0.aim)
-		c->aim0.refs--;
-	if (aim == c->aim1.aim)
-		c->aim1.refs--;
+	if (aim == c->pipe0.aim)
+		c->pipe0.refs--;
+	if (aim == c->pipe1.aim)
+		c->pipe1.refs--;
 	mutex_unlock(&c->start_mutex);
 	return 0;
 }
@@ -1327,13 +1327,13 @@ int most_deregister_aim(struct most_aim *aim)
 
 	list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
 		list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
-			if (c->aim0.aim == aim || c->aim1.aim == aim)
+			if (c->pipe0.aim == aim || c->pipe1.aim == aim)
 				aim->disconnect_channel(
 					c->iface, c->channel_id);
-			if (c->aim0.aim == aim)
-				c->aim0.aim = NULL;
-			if (c->aim1.aim == aim)
-				c->aim1.aim = NULL;
+			if (c->pipe0.aim == aim)
+				c->pipe0.aim = NULL;
+			if (c->pipe1.aim == aim)
+				c->pipe1.aim = NULL;
 		}
 	}
 	device_unregister(&aim->dev);
@@ -1479,14 +1479,14 @@ void most_deregister_interface(struct most_interface *iface)
 	inst = iface->priv;
 	for (i = 0; i < iface->num_channels; i++) {
 		c = inst->channel[i];
-		if (c->aim0.aim)
-			c->aim0.aim->disconnect_channel(c->iface,
+		if (c->pipe0.aim)
+			c->pipe0.aim->disconnect_channel(c->iface,
 							c->channel_id);
-		if (c->aim1.aim)
-			c->aim1.aim->disconnect_channel(c->iface,
+		if (c->pipe1.aim)
+			c->pipe1.aim->disconnect_channel(c->iface,
 							c->channel_id);
-		c->aim0.aim = NULL;
-		c->aim1.aim = NULL;
+		c->pipe0.aim = NULL;
+		c->pipe1.aim = NULL;
 		list_del(&c->list);
 		device_unregister(&c->dev);
 		kfree(c);
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 07/26] staging: most: core: use structure to pack driver specific data
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (4 preceding siblings ...)
  2017-10-13 14:32 ` [PATCH v2 06/26] staging: most: core: rename members aim* of struct most_channel Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 08/26] staging: most: core: track aim modules with linked list Christian Gromm
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch introduces the structure "mostcore" to bundle core specific
data structures.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 64 ++++++++++++++++++++++++---------------------
 1 file changed, 34 insertions(+), 30 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 9d37ace..1af5b1c 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -32,11 +32,19 @@
 #define MAX_CHANNELS	64
 #define STRING_SIZE	80
 
-static struct class *most_class;
-static struct device core_dev;
 static struct ida mdev_id;
 static int dummy_num_buffers;
 
+static struct mostcore {
+	struct device dev;
+	struct device_driver drv;
+	struct bus_type bus;
+	struct class *class;
+	struct list_head mod_list;
+} mc;
+
+#define to_driver(d) container_of(d, struct mostcore, drv);
+
 struct pipe {
 	struct most_aim *aim;
 	int refs;
@@ -98,15 +106,6 @@ int most_match(struct device *dev, struct device_driver *drv)
 		return 1;
 }
 
-static struct bus_type most_bus_type = {
-	.name = "most",
-	.match = most_match,
-};
-
-static struct device_driver mostcore = {
-	.name = "most_core",
-	.bus = &most_bus_type,
-};
 /**
  * list_pop_mbo - retrieves the first MBO of the list and removes it
  * @ptr: the list head to grab the MBO from.
@@ -1297,8 +1296,8 @@ int most_register_aim(struct most_aim *aim)
 		return -EINVAL;
 	}
 	aim->dev.init_name = aim->name;
-	aim->dev.bus = &most_bus_type;
-	aim->dev.parent = &core_dev;
+	aim->dev.bus = &mc.bus;
+	aim->dev.parent = &mc.dev;
 	aim->dev.groups = aim_attr_groups;
 	aim->dev.release = release_aim;
 	ret = device_register(&aim->dev);
@@ -1394,8 +1393,8 @@ int most_register_interface(struct most_interface *iface)
 	list_add_tail(&inst->list, &instance_list);
 	snprintf(name, STRING_SIZE, "mdev%d", id);
 	iface->dev.init_name = name;
-	iface->dev.bus = &most_bus_type;
-	iface->dev.parent = &core_dev;
+	iface->dev.bus = &mc.bus;
+	iface->dev.parent = &mc.dev;
 	iface->dev.groups = interface_attr_groups;
 	iface->dev.release = release_interface;
 	if (device_register(&iface->dev)) {
@@ -1560,47 +1559,52 @@ static int __init most_init(void)
 	INIT_LIST_HEAD(&aim_list);
 	ida_init(&mdev_id);
 
-	err = bus_register(&most_bus_type);
+	mc.bus.name = "most",
+	mc.bus.match = most_match,
+	mc.drv.name = "most_core",
+	mc.drv.bus = &mc.bus,
+
+	err = bus_register(&mc.bus);
 	if (err) {
 		pr_info("Cannot register most bus\n");
 		return err;
 	}
-	most_class = class_create(THIS_MODULE, "most");
-	if (IS_ERR(most_class)) {
+	mc.class = class_create(THIS_MODULE, "most");
+	if (IS_ERR(mc.class)) {
 		pr_info("No udev support.\n");
-		err = PTR_ERR(most_class);
+		err = PTR_ERR(mc.class);
 		goto exit_bus;
 	}
 
-	err = driver_register(&mostcore);
+	err = driver_register(&mc.drv);
 	if (err) {
 		pr_info("Cannot register core driver\n");
 		goto exit_class;
 	}
-	core_dev.init_name = "most_bus";
-	core_dev.release = release_most_sub;
-	if (device_register(&core_dev)) {
+	mc.dev.init_name = "most_bus";
+	mc.dev.release = release_most_sub;
+	if (device_register(&mc.dev)) {
 		err = -ENOMEM;
 		goto exit_driver;
 	}
 	return 0;
 
 exit_driver:
-	driver_unregister(&mostcore);
+	driver_unregister(&mc.drv);
 exit_class:
-	class_destroy(most_class);
+	class_destroy(mc.class);
 exit_bus:
-	bus_unregister(&most_bus_type);
+	bus_unregister(&mc.bus);
 	return err;
 }
 
 static void __exit most_exit(void)
 {
 	pr_info("exit core module\n");
-	device_unregister(&core_dev);
-	driver_unregister(&mostcore);
-	class_destroy(most_class);
-	bus_unregister(&most_bus_type);
+	device_unregister(&mc.dev);
+	driver_unregister(&mc.drv);
+	class_destroy(mc.class);
+	bus_unregister(&mc.bus);
 	ida_destroy(&mdev_id);
 }
 
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 08/26] staging: most: core: track aim modules with linked list
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (5 preceding siblings ...)
  2017-10-13 14:32 ` [PATCH v2 07/26] staging: most: core: use structure to pack driver specific data Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 09/26] staging: most: core: let core manage aim attributes Christian Gromm
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch makes the core keep track of the registered modules.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 6 +++---
 drivers/staging/most/core.h | 1 +
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 1af5b1c..01a1a37 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -553,8 +553,6 @@ static ssize_t interface_show(struct device *dev,
 /*		     ___     ___
  *		     ___A I M___
  */
-static struct list_head aim_list;
-
 static ssize_t links_show(struct device *dev, struct device_attribute *attr,
 			  char *buf)
 {
@@ -1305,6 +1303,7 @@ int most_register_aim(struct most_aim *aim)
 		pr_err("registering device %s failed\n", aim->name);
 		return ret;
 	}
+	list_add_tail(&aim->list, &mc.mod_list);
 	pr_info("registered new application interfacing module %s\n", aim->name);
 	return 0;
 }
@@ -1336,6 +1335,7 @@ int most_deregister_aim(struct most_aim *aim)
 		}
 	}
 	device_unregister(&aim->dev);
+	list_del(&aim->list);
 	pr_info("deregistering application interfacing module %s\n", aim->name);
 	return 0;
 }
@@ -1556,7 +1556,7 @@ static int __init most_init(void)
 
 	pr_info("init()\n");
 	INIT_LIST_HEAD(&instance_list);
-	INIT_LIST_HEAD(&aim_list);
+	INIT_LIST_HEAD(&mc.mod_list);
 	ida_init(&mdev_id);
 
 	mc.bus.name = "most",
diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h
index 588aadb..eb12c62 100644
--- a/drivers/staging/most/core.h
+++ b/drivers/staging/most/core.h
@@ -268,6 +268,7 @@ struct most_interface {
  */
 struct most_aim {
 	struct device dev;
+	struct list_head list;
 	const char *name;
 	int (*probe_channel)(struct most_interface *iface, int channel_idx,
 			     struct most_channel_config *cfg, char *name);
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 09/26] staging: most: core: let core manage aim attributes
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (6 preceding siblings ...)
  2017-10-13 14:32 ` [PATCH v2 08/26] staging: most: core: track aim modules with linked list Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 10/26] staging: most: core: remove struct device from struct most_aim Christian Gromm
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch creates a new attribute group to manage the attributes
of a registered aim module in sysfs and changes the show and store
functions accordingly.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 109 +++++++++++++++++++++++++++++---------------
 1 file changed, 73 insertions(+), 36 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 01a1a37..45afec9 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -553,28 +553,57 @@ static ssize_t interface_show(struct device *dev,
 /*		     ___     ___
  *		     ___A I M___
  */
-static ssize_t links_show(struct device *dev, struct device_attribute *attr,
-			  char *buf)
+static struct most_aim *match_module(char *name)
+{
+	struct most_aim *aim;
+
+	list_for_each_entry(aim, &mc.mod_list, list) {
+		if (!strcmp(aim->name, name))
+			return aim;
+	}
+	return NULL;
+}
+
+static ssize_t links_show(struct device_driver *drv, char *buf)
 {
 	struct most_channel *c;
 	struct most_inst_obj *i;
-	struct most_aim *aim = to_most_aim(dev);
 	int offs = 0;
 
 	list_for_each_entry(i, &instance_list, list) {
 		list_for_each_entry(c, &i->channel_list, list) {
-			if (c->pipe0.aim == aim || c->pipe1.aim == aim) {
-				offs += snprintf(buf + offs, PAGE_SIZE - offs,
-						 "%s:%s\n",
+			if (c->pipe0.aim) {
+				offs += snprintf(buf + offs,
+						 PAGE_SIZE - offs,
+						 "%s:%s:%s\n",
+						 c->pipe0.aim->name,
+						 dev_name(&i->iface->dev),
+						 dev_name(&c->dev));
+			}
+			if (c->pipe1.aim) {
+				offs += snprintf(buf + offs,
+						 PAGE_SIZE - offs,
+						 "%s:%s:%s\n",
+						 c->pipe1.aim->name,
 						 dev_name(&i->iface->dev),
 						 dev_name(&c->dev));
 			}
 		}
 	}
-
 	return offs;
 }
 
+static ssize_t modules_show(struct device_driver *drv, char *buf)
+{
+	struct most_aim *aim;
+	int offs = 0;
+
+	list_for_each_entry(aim, &mc.mod_list, list) {
+		offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s\n",
+				 aim->name);
+	}
+	return offs;
+}
 /**
  * split_string - parses and changes string in the buffer buf and
  * splits it into two mandatory and one optional substrings.
@@ -597,7 +626,7 @@ static ssize_t links_show(struct device *dev, struct device_attribute *attr,
  * Input: "mdev1:ep81"
  * Output: *a -> "mdev1", *b -> "ep81", *c == NULL
  */
-static int split_string(char *buf, char **a, char **b, char **c)
+static int split_string(char *buf, char **a, char **b, char **c, char **d)
 {
 	*a = strsep(&buf, ":");
 	if (!*a)
@@ -607,8 +636,12 @@ static int split_string(char *buf, char **a, char **b, char **c)
 	if (!*b)
 		return -EIO;
 
-	if (c)
-		*c = strsep(&buf, ":\n");
+	*c = strsep(&buf, ":\n");
+	if (!*c)
+		return -EIO;
+
+	if (d)
+		*d = strsep(&buf, ":\n");
 
 	return 0;
 }
@@ -692,38 +725,38 @@ static int link_channel_to_aim(struct most_channel *c, struct most_aim *aim,
  * (1) would create the device node /dev/my_rxchannel
  * (2) would create the device node /dev/mdev1-ep81
  */
-static ssize_t add_link_store(struct device *dev,
-			      struct device_attribute *attr,
+static ssize_t add_link_store(struct device_driver *drv,
 			      const char *buf,
 			      size_t len)
 {
 	struct most_channel *c;
-	struct most_aim *aim = to_most_aim(dev);
+	struct most_aim *aim;
 	char buffer[STRING_SIZE];
 	char *mdev;
 	char *mdev_ch;
-	char *mdev_devnod;
+	char *aim_name;
+	char *aim_param;
 	char devnod_buf[STRING_SIZE];
 	int ret;
 	size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
 
 	strlcpy(buffer, buf, max_len);
 
-	ret = split_string(buffer, &mdev, &mdev_ch, &mdev_devnod);
+	ret = split_string(buffer, &mdev, &mdev_ch, &aim_name, &aim_param);
 	if (ret)
 		return ret;
-
-	if (!mdev_devnod || *mdev_devnod == 0) {
+	aim = match_module(aim_name);
+	if (!aim_param || *aim_param == 0) {
 		snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev,
 			 mdev_ch);
-		mdev_devnod = devnod_buf;
+		aim_param = devnod_buf;
 	}
 
 	c = get_channel_by_name(mdev, mdev_ch);
 	if (IS_ERR(c))
 		return -ENODEV;
 
-	ret = link_channel_to_aim(c, aim, mdev_devnod);
+	ret = link_channel_to_aim(c, aim, aim_param);
 	if (ret)
 		return ret;
 
@@ -740,24 +773,24 @@ static ssize_t add_link_store(struct device *dev,
  * Example:
  * echo "mdev0:ep81" >remove_link
  */
-static ssize_t remove_link_store(struct device *dev,
-				 struct device_attribute *attr,
+static ssize_t remove_link_store(struct device_driver *drv,
 				 const char *buf,
 				 size_t len)
 {
 	struct most_channel *c;
-	struct most_aim *aim = to_most_aim(dev);
+	struct most_aim *aim;
 	char buffer[STRING_SIZE];
 	char *mdev;
 	char *mdev_ch;
+	char *aim_name;
 	int ret;
 	size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
 
 	strlcpy(buffer, buf, max_len);
-	ret = split_string(buffer, &mdev, &mdev_ch, NULL);
+	ret = split_string(buffer, &mdev, &mdev_ch, &aim_name, NULL);
 	if (ret)
 		return ret;
-
+	aim = match_module(aim_name);
 	c = get_channel_by_name(mdev, mdev_ch);
 	if (IS_ERR(c))
 		return -ENODEV;
@@ -771,23 +804,27 @@ static ssize_t remove_link_store(struct device *dev,
 	return len;
 }
 
-static DEVICE_ATTR_RO(links);
-static DEVICE_ATTR_WO(add_link);
-static DEVICE_ATTR_WO(remove_link);
+#define DRV_ATTR(_name)  &driver_attr_##_name.attr
+
+static DRIVER_ATTR_RO(links);
+static DRIVER_ATTR_RO(modules);
+static DRIVER_ATTR_WO(add_link);
+static DRIVER_ATTR_WO(remove_link);
 
-static struct attribute *aim_attrs[] = {
-	DEV_ATTR(links),
-	DEV_ATTR(add_link),
-	DEV_ATTR(remove_link),
+static struct attribute *module_attrs[] = {
+	DRV_ATTR(links),
+	DRV_ATTR(modules),
+	DRV_ATTR(add_link),
+	DRV_ATTR(remove_link),
 	NULL,
 };
 
-static struct attribute_group aim_attr_group = {
-	.attrs = aim_attrs,
+static struct attribute_group module_attr_group = {
+	.attrs = module_attrs,
 };
 
-static const struct attribute_group *aim_attr_groups[] = {
-	&aim_attr_group,
+static const struct attribute_group *module_attr_groups[] = {
+	&module_attr_group,
 	NULL,
 };
 /*		     ___       ___
@@ -1296,7 +1333,6 @@ int most_register_aim(struct most_aim *aim)
 	aim->dev.init_name = aim->name;
 	aim->dev.bus = &mc.bus;
 	aim->dev.parent = &mc.dev;
-	aim->dev.groups = aim_attr_groups;
 	aim->dev.release = release_aim;
 	ret = device_register(&aim->dev);
 	if (ret) {
@@ -1563,6 +1599,7 @@ static int __init most_init(void)
 	mc.bus.match = most_match,
 	mc.drv.name = "most_core",
 	mc.drv.bus = &mc.bus,
+	mc.drv.groups = module_attr_groups;
 
 	err = bus_register(&mc.bus);
 	if (err) {
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 10/26] staging: most: core: remove struct device from struct most_aim
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (7 preceding siblings ...)
  2017-10-13 14:32 ` [PATCH v2 09/26] staging: most: core: let core manage aim attributes Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 11/26] staging: most: core: fix header file mostcore.h Christian Gromm
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch removes the struct device from the most_aim as it is not
needed.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 17 -----------------
 drivers/staging/most/core.h |  1 -
 2 files changed, 18 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 45afec9..3cf72a1 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -1313,32 +1313,16 @@ int most_stop_channel(struct most_interface *iface, int id,
 }
 EXPORT_SYMBOL_GPL(most_stop_channel);
 
-void release_aim(struct device *dev)
-{
-	pr_info("releasing aim %s\n", dev_name(dev));
-}
-
 /**
  * most_register_aim - registers an AIM (driver) with the core
  * @aim: instance of AIM to be registered
  */
 int most_register_aim(struct most_aim *aim)
 {
-	int ret;
-
 	if (!aim) {
 		pr_err("Bad driver\n");
 		return -EINVAL;
 	}
-	aim->dev.init_name = aim->name;
-	aim->dev.bus = &mc.bus;
-	aim->dev.parent = &mc.dev;
-	aim->dev.release = release_aim;
-	ret = device_register(&aim->dev);
-	if (ret) {
-		pr_err("registering device %s failed\n", aim->name);
-		return ret;
-	}
 	list_add_tail(&aim->list, &mc.mod_list);
 	pr_info("registered new application interfacing module %s\n", aim->name);
 	return 0;
@@ -1370,7 +1354,6 @@ int most_deregister_aim(struct most_aim *aim)
 				c->pipe1.aim = NULL;
 		}
 	}
-	device_unregister(&aim->dev);
 	list_del(&aim->list);
 	pr_info("deregistering application interfacing module %s\n", aim->name);
 	return 0;
diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h
index eb12c62..c449e55 100644
--- a/drivers/staging/most/core.h
+++ b/drivers/staging/most/core.h
@@ -267,7 +267,6 @@ struct most_interface {
  * @context: context pointer to be used by mostcore
  */
 struct most_aim {
-	struct device dev;
 	struct list_head list;
 	const char *name;
 	int (*probe_channel)(struct most_interface *iface, int channel_idx,
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 11/26] staging: most: core: fix header file mostcore.h
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (8 preceding siblings ...)
  2017-10-13 14:32 ` [PATCH v2 10/26] staging: most: core: remove struct device from struct most_aim Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 12/26] staging: most: core: rename function Christian Gromm
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch includes the header device.h and removes the forward
declaration of kobject.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h
index c449e55..82e64b2 100644
--- a/drivers/staging/most/core.h
+++ b/drivers/staging/most/core.h
@@ -23,8 +23,8 @@
 #define __MOST_CORE_H__
 
 #include <linux/types.h>
+#include <linux/device.h>
 
-struct kobject;
 struct module;
 
 /**
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 12/26] staging: most: core: rename function
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (9 preceding siblings ...)
  2017-10-13 14:32 ` [PATCH v2 11/26] staging: most: core: fix header file mostcore.h Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 13/26] staging: most: core: replace struct most_inst_obj with struct interface_private Christian Gromm
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

The core module used to have two functions to find a certain
channel. One by name and one by interface. Since no channel is
searched by its interface name anymore the by_name suffix is
rendered redundant. This patch renames the function accordingly.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 3cf72a1..a68f0cc 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -647,13 +647,13 @@ static int split_string(char *buf, char **a, char **b, char **c, char **d)
 }
 
 /**
- * get_channel_by_name - get pointer to channel object
+ * get_channel - get pointer to channel object
  * @mdev: name of the device instance
  * @mdev_ch: name of the respective channel
  *
  * This retrieves the pointer to a channel object.
  */
-static struct most_channel *get_channel_by_name(char *mdev, char *mdev_ch)
+static struct most_channel *get_channel(char *mdev, char *mdev_ch)
 {
 	struct most_channel *c, *tmp;
 	struct most_inst_obj *i, *i_tmp;
@@ -752,7 +752,7 @@ static ssize_t add_link_store(struct device_driver *drv,
 		aim_param = devnod_buf;
 	}
 
-	c = get_channel_by_name(mdev, mdev_ch);
+	c = get_channel(mdev, mdev_ch);
 	if (IS_ERR(c))
 		return -ENODEV;
 
@@ -791,7 +791,7 @@ static ssize_t remove_link_store(struct device_driver *drv,
 	if (ret)
 		return ret;
 	aim = match_module(aim_name);
-	c = get_channel_by_name(mdev, mdev_ch);
+	c = get_channel(mdev, mdev_ch);
 	if (IS_ERR(c))
 		return -ENODEV;
 
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 13/26] staging: most: core: replace struct most_inst_obj with struct interface_private
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (10 preceding siblings ...)
  2017-10-13 14:32 ` [PATCH v2 12/26] staging: most: core: rename function Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 14/26] staging: most: core: make channel name accessible from struct most_channel Christian Gromm
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: driverdev-devel, Christian Gromm

This patch introduces struct interface_private as a replacement for
the struct most_inst_obj. This structure holds private data that is
only needed by the core module and will be accessed by a pointer from
within the most_interface structure. As a result of this replacement
the bus helper functions are used to search for devices.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 201 +++++++++++++++++++++-----------------------
 drivers/staging/most/core.h |   2 +
 2 files changed, 99 insertions(+), 104 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index a68f0cc..69d24f6 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -62,7 +62,6 @@ struct most_channel {
 	struct mutex nq_mutex; /* nq thread synchronization */
 	int is_starving;
 	struct most_interface *iface;
-	struct most_inst_obj *inst;
 	struct most_channel_config cfg;
 	bool keep_mbo;
 	bool enqueue_halt;
@@ -79,12 +78,11 @@ struct most_channel {
 
 #define to_channel(d) container_of(d, struct most_channel, dev)
 
-struct most_inst_obj {
+struct interface_private {
 	int dev_id;
-	struct most_interface *iface;
-	struct list_head channel_list;
+	char name[STRING_SIZE];
 	struct most_channel *channel[MAX_CHANNELS];
-	struct list_head list;
+	struct list_head channel_list;
 };
 
 static const struct {
@@ -490,9 +488,6 @@ static ssize_t set_packets_per_xact_store(struct device *dev,
 /*		     ___	       ___
  *		     ___I N S T A N C E___
  */
-
-static struct list_head instance_list;
-
 static ssize_t description_show(struct device *dev,
 				struct device_attribute *attr,
 				char *buf)
@@ -564,33 +559,38 @@ static struct most_aim *match_module(char *name)
 	return NULL;
 }
 
-static ssize_t links_show(struct device_driver *drv, char *buf)
+int print_links(struct device *dev, void *data)
 {
-	struct most_channel *c;
-	struct most_inst_obj *i;
 	int offs = 0;
+	char *buf = data;
+	struct most_channel *c;
+	struct most_interface *iface = to_most_interface(dev);
 
-	list_for_each_entry(i, &instance_list, list) {
-		list_for_each_entry(c, &i->channel_list, list) {
-			if (c->pipe0.aim) {
-				offs += snprintf(buf + offs,
-						 PAGE_SIZE - offs,
-						 "%s:%s:%s\n",
-						 c->pipe0.aim->name,
-						 dev_name(&i->iface->dev),
-						 dev_name(&c->dev));
-			}
-			if (c->pipe1.aim) {
-				offs += snprintf(buf + offs,
-						 PAGE_SIZE - offs,
-						 "%s:%s:%s\n",
-						 c->pipe1.aim->name,
-						 dev_name(&i->iface->dev),
-						 dev_name(&c->dev));
-			}
+	list_for_each_entry(c, &iface->p->channel_list, list) {
+		if (c->pipe0.aim) {
+			offs += snprintf(buf + offs,
+					 PAGE_SIZE - offs,
+					 "%s:%s:%s\n",
+					 c->pipe0.aim->name,
+					 dev_name(&iface->dev),
+					 dev_name(&c->dev));
+		}
+		if (c->pipe1.aim) {
+			offs += snprintf(buf + offs,
+					 PAGE_SIZE - offs,
+					 "%s:%s:%s\n",
+					 c->pipe1.aim->name,
+					 dev_name(&iface->dev),
+					 dev_name(&c->dev));
 		}
 	}
-	return offs;
+	return 0;
+}
+
+static ssize_t links_show(struct device_driver *drv, char *buf)
+{
+	bus_for_each_dev(&mc.bus, NULL, buf, print_links);
+	return strlen(buf);
 }
 
 static ssize_t modules_show(struct device_driver *drv, char *buf)
@@ -646,6 +646,13 @@ static int split_string(char *buf, char **a, char **b, char **c, char **d)
 	return 0;
 }
 
+static int match_bus_dev(struct device *dev, void *data)
+{
+	char *mdev_name = data;
+
+	return !strcmp(dev_name(dev), mdev_name);
+}
+
 /**
  * get_channel - get pointer to channel object
  * @mdev: name of the device instance
@@ -655,28 +662,19 @@ static int split_string(char *buf, char **a, char **b, char **c, char **d)
  */
 static struct most_channel *get_channel(char *mdev, char *mdev_ch)
 {
+	struct device *dev = NULL;
+	struct most_interface *iface;
 	struct most_channel *c, *tmp;
-	struct most_inst_obj *i, *i_tmp;
-	int found = 0;
 
-	list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
-		if (!strcmp(dev_name(&i->iface->dev), mdev)) {
-			found++;
-			break;
-		}
-	}
-	if (unlikely(!found))
-		return ERR_PTR(-EIO);
-
-	list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
-		if (!strcmp(dev_name(&c->dev), mdev_ch)) {
-			found++;
-			break;
-		}
+	dev = bus_find_device(&mc.bus, NULL, mdev, match_bus_dev);
+	if (!dev)
+		return NULL;
+	iface = to_most_interface(dev);
+	list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) {
+		if (!strcmp(dev_name(&c->dev), mdev_ch))
+			return c;
 	}
-	if (unlikely(found < 2))
-		return ERR_PTR(-EIO);
-	return c;
+	return NULL;
 }
 
 static int link_channel_to_aim(struct most_channel *c, struct most_aim *aim,
@@ -753,7 +751,7 @@ static ssize_t add_link_store(struct device_driver *drv,
 	}
 
 	c = get_channel(mdev, mdev_ch);
-	if (IS_ERR(c))
+	if (!c)
 		return -ENODEV;
 
 	ret = link_channel_to_aim(c, aim, aim_param);
@@ -792,7 +790,7 @@ static ssize_t remove_link_store(struct device_driver *drv,
 		return ret;
 	aim = match_module(aim_name);
 	c = get_channel(mdev, mdev_ch);
-	if (IS_ERR(c))
+	if (!c)
 		return -ENODEV;
 
 	if (aim->disconnect_channel(c->iface, c->channel_id))
@@ -1051,8 +1049,7 @@ static void most_write_completion(struct mbo *mbo)
 
 int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim)
 {
-	struct most_inst_obj *inst = iface->priv;
-	struct most_channel *c = inst->channel[id];
+	struct most_channel *c = iface->p->channel[id];
 	unsigned long flags;
 	int empty;
 
@@ -1084,11 +1081,10 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id,
 {
 	struct mbo *mbo;
 	struct most_channel *c;
-	struct most_inst_obj *inst = iface->priv;
 	unsigned long flags;
 	int *num_buffers_ptr;
 
-	c = inst->channel[id];
+	c = iface->p->channel[id];
 	if (unlikely(!c))
 		return NULL;
 
@@ -1190,8 +1186,7 @@ int most_start_channel(struct most_interface *iface, int id,
 {
 	int num_buffer;
 	int ret;
-	struct most_inst_obj *inst = iface->priv;
-	struct most_channel *c = inst->channel[id];
+	struct most_channel *c = iface->p->channel[id];
 
 	if (unlikely(!c))
 		return -EINVAL;
@@ -1259,15 +1254,13 @@ int most_start_channel(struct most_interface *iface, int id,
 int most_stop_channel(struct most_interface *iface, int id,
 		      struct most_aim *aim)
 {
-	struct most_inst_obj *inst;
 	struct most_channel *c;
 
 	if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) {
 		pr_err("Bad interface or index out of range\n");
 		return -EINVAL;
 	}
-	inst = iface->priv;
-	c = inst->channel[id];
+	c = iface->p->channel[id];
 	if (unlikely(!c))
 		return -EINVAL;
 
@@ -1329,33 +1322,38 @@ int most_register_aim(struct most_aim *aim)
 }
 EXPORT_SYMBOL_GPL(most_register_aim);
 
+static int disconnect_channels(struct device *dev, void *data)
+{
+	struct most_interface *iface;
+	struct most_channel *c, *tmp;
+	struct most_aim *aim = data;
+
+	iface = to_most_interface(dev);
+	list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) {
+		if (c->pipe0.aim == aim || c->pipe1.aim == aim)
+			aim->disconnect_channel(c->iface, c->channel_id);
+		if (c->pipe0.aim == aim)
+			c->pipe0.aim = NULL;
+		if (c->pipe1.aim == aim)
+			c->pipe1.aim = NULL;
+	}
+	return 0;
+}
+
 /**
  * most_deregister_aim - deregisters an AIM (driver) with the core
  * @aim: AIM to be removed
  */
 int most_deregister_aim(struct most_aim *aim)
 {
-	struct most_channel *c, *tmp;
-	struct most_inst_obj *i, *i_tmp;
-
 	if (!aim) {
 		pr_err("Bad driver\n");
 		return -EINVAL;
 	}
 
-	list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
-		list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
-			if (c->pipe0.aim == aim || c->pipe1.aim == aim)
-				aim->disconnect_channel(
-					c->iface, c->channel_id);
-			if (c->pipe0.aim == aim)
-				c->pipe0.aim = NULL;
-			if (c->pipe1.aim == aim)
-				c->pipe1.aim = NULL;
-		}
-	}
+	bus_for_each_dev(&mc.bus, NULL, aim, disconnect_channels);
 	list_del(&aim->list);
-	pr_info("deregistering application interfacing module %s\n", aim->name);
+	pr_info("deregistering module %s\n", aim->name);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(most_deregister_aim);
@@ -1381,10 +1379,8 @@ int most_register_interface(struct most_interface *iface)
 {
 	unsigned int i;
 	int id;
-	char name[STRING_SIZE];
 	char channel_name[STRING_SIZE];
 	struct most_channel *c;
-	struct most_inst_obj *inst;
 
 	if (!iface || !iface->enqueue || !iface->configure ||
 	    !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) {
@@ -1398,27 +1394,24 @@ int most_register_interface(struct most_interface *iface)
 		return id;
 	}
 
-	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
-	if (!inst) {
+	iface->p = kzalloc(sizeof(*iface->p), GFP_KERNEL);
+	if (!iface->p) {
 		pr_info("Failed to allocate interface instance\n");
 		ida_simple_remove(&mdev_id, id);
 		return -ENOMEM;
 	}
 
-	iface->priv = inst;
-	INIT_LIST_HEAD(&inst->channel_list);
-	inst->iface = iface;
-	inst->dev_id = id;
-	list_add_tail(&inst->list, &instance_list);
-	snprintf(name, STRING_SIZE, "mdev%d", id);
-	iface->dev.init_name = name;
+	INIT_LIST_HEAD(&iface->p->channel_list);
+	iface->p->dev_id = id;
+	snprintf(iface->p->name, STRING_SIZE, "mdev%d", id);
+	iface->dev.init_name = iface->p->name;
 	iface->dev.bus = &mc.bus;
 	iface->dev.parent = &mc.dev;
 	iface->dev.groups = interface_attr_groups;
 	iface->dev.release = release_interface;
 	if (device_register(&iface->dev)) {
 		pr_err("registering iface->dev failed\n");
-		kfree(inst);
+		kfree(iface->p);
 		ida_simple_remove(&mdev_id, id);
 		return -ENOMEM;
 	}
@@ -1431,23 +1424,20 @@ int most_register_interface(struct most_interface *iface)
 		else
 			snprintf(channel_name, STRING_SIZE, "%s", name_suffix);
 
-		/* this increments the reference count of this instance */
 		c = kzalloc(sizeof(*c), GFP_KERNEL);
 		if (!c)
 			goto free_instance;
-		//snprintf(c->dev.init_name, STRING_SIZE, channel_name);
 		c->dev.init_name = channel_name;
 		c->dev.parent = &iface->dev;
 		c->dev.groups = channel_attr_groups;
 		c->dev.release = release_channel;
 		if (device_register(&c->dev)) {
 			pr_err("registering c->dev failed\n");
-			goto free_instance;
+			goto free_instance_nodev;
 		}
-		inst->channel[i] = c;
+		iface->p->channel[i] = c;
 		c->is_starving = 0;
 		c->iface = iface;
-		c->inst = inst;
 		c->channel_id = i;
 		c->keep_mbo = false;
 		c->enqueue_halt = false;
@@ -1466,14 +1456,22 @@ int most_register_interface(struct most_interface *iface)
 		atomic_set(&c->mbo_ref, 0);
 		mutex_init(&c->start_mutex);
 		mutex_init(&c->nq_mutex);
-		list_add_tail(&c->list, &inst->channel_list);
+		list_add_tail(&c->list, &iface->p->channel_list);
 	}
 	pr_info("registered new MOST device mdev%d (%s)\n",
 		id, iface->description);
 	return 0;
 
+free_instance_nodev:
+	kfree(c);
+
 free_instance:
-	pr_info("Failed allocate channel(s)\n");
+	while (i > 0) {
+		c = iface->p->channel[--i];
+		device_unregister(&c->dev);
+		kfree(c);
+	}
+	kfree(iface->p);
 	device_unregister(&iface->dev);
 	ida_simple_remove(&mdev_id, id);
 	return -ENOMEM;
@@ -1491,12 +1489,10 @@ void most_deregister_interface(struct most_interface *iface)
 {
 	int i;
 	struct most_channel *c;
-	struct most_inst_obj *inst;
 
 	pr_info("deregistering MOST device %s (%s)\n", dev_name(&iface->dev), iface->description);
-	inst = iface->priv;
 	for (i = 0; i < iface->num_channels; i++) {
-		c = inst->channel[i];
+		c = iface->p->channel[i];
 		if (c->pipe0.aim)
 			c->pipe0.aim->disconnect_channel(c->iface,
 							c->channel_id);
@@ -1510,8 +1506,8 @@ void most_deregister_interface(struct most_interface *iface)
 		kfree(c);
 	}
 
-	ida_simple_remove(&mdev_id, inst->dev_id);
-	kfree(inst);
+	ida_simple_remove(&mdev_id, iface->p->dev_id);
+	kfree(iface->p);
 	device_unregister(&iface->dev);
 }
 EXPORT_SYMBOL_GPL(most_deregister_interface);
@@ -1528,8 +1524,7 @@ void most_deregister_interface(struct most_interface *iface)
  */
 void most_stop_enqueue(struct most_interface *iface, int id)
 {
-	struct most_inst_obj *inst = iface->priv;
-	struct most_channel *c = inst->channel[id];
+	struct most_channel *c = iface->p->channel[id];
 
 	if (!c)
 		return;
@@ -1550,8 +1545,7 @@ void most_stop_enqueue(struct most_interface *iface, int id)
  */
 void most_resume_enqueue(struct most_interface *iface, int id)
 {
-	struct most_inst_obj *inst = iface->priv;
-	struct most_channel *c = inst->channel[id];
+	struct most_channel *c = iface->p->channel[id];
 
 	if (!c)
 		return;
@@ -1574,7 +1568,6 @@ static int __init most_init(void)
 	int err;
 
 	pr_info("init()\n");
-	INIT_LIST_HEAD(&instance_list);
 	INIT_LIST_HEAD(&mc.mod_list);
 	ida_init(&mdev_id);
 
diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h
index 82e64b2..af40f61 100644
--- a/drivers/staging/most/core.h
+++ b/drivers/staging/most/core.h
@@ -26,6 +26,7 @@
 #include <linux/device.h>
 
 struct module;
+struct interface_private;
 
 /**
  * Interface type
@@ -254,6 +255,7 @@ struct most_interface {
 						   unsigned char link_stat,
 						   unsigned char *mac_addr));
 	void *priv;
+	struct interface_private *p;
 };
 
 #define to_most_interface(d) container_of(d, struct most_interface, dev)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 14/26] staging: most: core: make channel name accessible from struct most_channel
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (11 preceding siblings ...)
  2017-10-13 14:32 ` [PATCH v2 13/26] staging: most: core: replace struct most_inst_obj with struct interface_private Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:32 ` [PATCH v2 15/26] staging: most: core: remove context pointer from struct most_aim Christian Gromm
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch stores a channel's name inside the most_channel structure,
hence making it accessible outside of function most_register_interface.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 69d24f6..50b57de 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -57,6 +57,7 @@ struct most_channel {
 	atomic_t mbo_ref;
 	atomic_t mbo_nq_level;
 	u16 channel_id;
+	char name[STRING_SIZE];
 	bool is_poisoned;
 	struct mutex start_mutex;
 	struct mutex nq_mutex; /* nq thread synchronization */
@@ -1379,7 +1380,6 @@ int most_register_interface(struct most_interface *iface)
 {
 	unsigned int i;
 	int id;
-	char channel_name[STRING_SIZE];
 	struct most_channel *c;
 
 	if (!iface || !iface->enqueue || !iface->configure ||
@@ -1419,15 +1419,14 @@ int most_register_interface(struct most_interface *iface)
 	for (i = 0; i < iface->num_channels; i++) {
 		const char *name_suffix = iface->channel_vector[i].name_suffix;
 
-		if (!name_suffix)
-			snprintf(channel_name, STRING_SIZE, "ch%d", i);
-		else
-			snprintf(channel_name, STRING_SIZE, "%s", name_suffix);
-
 		c = kzalloc(sizeof(*c), GFP_KERNEL);
 		if (!c)
 			goto free_instance;
-		c->dev.init_name = channel_name;
+		if (!name_suffix)
+			snprintf(c->name, STRING_SIZE, "ch%d", i);
+		else
+			snprintf(c->name, STRING_SIZE, "%s", name_suffix);
+		c->dev.init_name = c->name;
 		c->dev.parent = &iface->dev;
 		c->dev.groups = channel_attr_groups;
 		c->dev.release = release_channel;
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 15/26] staging: most: core: remove context pointer from struct most_aim
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (12 preceding siblings ...)
  2017-10-13 14:32 ` [PATCH v2 14/26] staging: most: core: make channel name accessible from struct most_channel Christian Gromm
@ 2017-10-13 14:32 ` Christian Gromm
  2017-10-13 14:33 ` [PATCH v2 16/26] staging: most: usb: remove pointer initialization Christian Gromm
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:32 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch removes the context pointer that was meant to provide the
opportunity to store context information.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h
index af40f61..09fa472 100644
--- a/drivers/staging/most/core.h
+++ b/drivers/staging/most/core.h
@@ -277,7 +277,6 @@ struct most_aim {
 				  int channel_idx);
 	int (*rx_completion)(struct mbo *mbo);
 	int (*tx_completion)(struct most_interface *iface, int channel_idx);
-	void *context;
 };
 
 #define to_most_aim(d) container_of(d, struct most_aim, dev)
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 16/26] staging: most: usb: remove pointer initialization
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (13 preceding siblings ...)
  2017-10-13 14:32 ` [PATCH v2 15/26] staging: most: core: remove context pointer from struct most_aim Christian Gromm
@ 2017-10-13 14:33 ` Christian Gromm
  2017-10-13 14:33 ` [PATCH v2 17/26] staging: most: change designator for modules interfacing userspace Christian Gromm
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:33 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch removes the initialization of the priv pointer of the
most_interface structure.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/usb/usb.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c
index 9e2a270..0624ca9 100644
--- a/drivers/staging/most/usb/usb.c
+++ b/drivers/staging/most/usb/usb.c
@@ -1043,8 +1043,6 @@ static ssize_t value_store(struct device *dev, struct device_attribute *attr,
 		goto exit_free1;
 
 	mdev->iface.channel_vector = mdev->cap;
-	mdev->iface.priv = NULL;
-
 	mdev->ep_address =
 		kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL);
 	if (!mdev->ep_address)
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 17/26] staging: most: change designator for modules interfacing userspace
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (14 preceding siblings ...)
  2017-10-13 14:33 ` [PATCH v2 16/26] staging: most: usb: remove pointer initialization Christian Gromm
@ 2017-10-13 14:33 ` Christian Gromm
  2017-10-13 14:33 ` [PATCH v2 18/26] staging: most: core: fix comment sections Christian Gromm
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:33 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

A module that is meant to make up the userspace experience of the driver
is no longer referred to as AIM. Instead it is denoted as a component of
the core. Further, it is understood as an integral part of the core, the
purpose of which is to meaningfully enhance the core with new features
(interface the userspace in a certain way). Therefore, this patch renames
aim with component or its abbreviation comp.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/cdev/cdev.c   | 143 +++++++++++-----------
 drivers/staging/most/core.c        | 236 ++++++++++++++++++-------------------
 drivers/staging/most/core.h        |  15 ++-
 drivers/staging/most/net/net.c     |  47 ++++----
 drivers/staging/most/sound/sound.c |  18 +--
 drivers/staging/most/video/video.c | 157 ++++++++++++------------
 6 files changed, 305 insertions(+), 311 deletions(-)

diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c
index 4b4c112..373baf2 100644
--- a/drivers/staging/most/cdev/cdev.c
+++ b/drivers/staging/most/cdev/cdev.c
@@ -24,13 +24,13 @@
 #include <linux/idr.h>
 #include <most/core.h>
 
-static dev_t aim_devno;
-static struct class *aim_class;
+static dev_t comp_devno;
+static struct class *comp_class;
 static struct ida minor_id;
 static unsigned int major;
-static struct most_aim cdev_aim;
+static struct core_component cdev_comp;
 
-struct aim_channel {
+struct comp_channel {
 	wait_queue_head_t wq;
 	spinlock_t unlink;	/* synchronization lock to unlink channels */
 	struct cdev cdev;
@@ -46,28 +46,28 @@ struct aim_channel {
 	struct list_head list;
 };
 
-#define to_channel(d) container_of(d, struct aim_channel, cdev)
+#define to_channel(d) container_of(d, struct comp_channel, cdev)
 static struct list_head channel_list;
 static spinlock_t ch_list_lock;
 
-static inline bool ch_has_mbo(struct aim_channel *c)
+static inline bool ch_has_mbo(struct comp_channel *c)
 {
-	return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0;
+	return channel_has_mbo(c->iface, c->channel_id, &cdev_comp) > 0;
 }
 
-static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo)
+static inline bool ch_get_mbo(struct comp_channel *c, struct mbo **mbo)
 {
 	if (!kfifo_peek(&c->fifo, mbo)) {
-		*mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim);
+		*mbo = most_get_mbo(c->iface, c->channel_id, &cdev_comp);
 		if (*mbo)
 			kfifo_in(&c->fifo, mbo, 1);
 	}
 	return *mbo;
 }
 
-static struct aim_channel *get_channel(struct most_interface *iface, int id)
+static struct comp_channel *get_channel(struct most_interface *iface, int id)
 {
-	struct aim_channel *c, *tmp;
+	struct comp_channel *c, *tmp;
 	unsigned long flags;
 	int found_channel = 0;
 
@@ -84,27 +84,27 @@ static struct aim_channel *get_channel(struct most_interface *iface, int id)
 	return c;
 }
 
-static void stop_channel(struct aim_channel *c)
+static void stop_channel(struct comp_channel *c)
 {
 	struct mbo *mbo;
 
 	while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1))
 		most_put_mbo(mbo);
-	most_stop_channel(c->iface, c->channel_id, &cdev_aim);
+	most_stop_channel(c->iface, c->channel_id, &cdev_comp);
 }
 
-static void destroy_cdev(struct aim_channel *c)
+static void destroy_cdev(struct comp_channel *c)
 {
 	unsigned long flags;
 
-	device_destroy(aim_class, c->devno);
+	device_destroy(comp_class, c->devno);
 	cdev_del(&c->cdev);
 	spin_lock_irqsave(&ch_list_lock, flags);
 	list_del(&c->list);
 	spin_unlock_irqrestore(&ch_list_lock, flags);
 }
 
-static void destroy_channel(struct aim_channel *c)
+static void destroy_channel(struct comp_channel *c)
 {
 	ida_simple_remove(&minor_id, MINOR(c->devno));
 	kfifo_free(&c->fifo);
@@ -112,16 +112,16 @@ static void destroy_channel(struct aim_channel *c)
 }
 
 /**
- * aim_open - implements the syscall to open the device
+ * comp_open - implements the syscall to open the device
  * @inode: inode pointer
  * @filp: file pointer
  *
  * This stores the channel pointer in the private data field of
  * the file structure and activates the channel within the core.
  */
-static int aim_open(struct inode *inode, struct file *filp)
+static int comp_open(struct inode *inode, struct file *filp)
 {
-	struct aim_channel *c;
+	struct comp_channel *c;
 	int ret;
 
 	c = to_channel(inode->i_cdev);
@@ -149,7 +149,7 @@ static int aim_open(struct inode *inode, struct file *filp)
 	}
 
 	c->mbo_offs = 0;
-	ret = most_start_channel(c->iface, c->channel_id, &cdev_aim);
+	ret = most_start_channel(c->iface, c->channel_id, &cdev_comp);
 	if (!ret)
 		c->access_ref = 1;
 	mutex_unlock(&c->io_mutex);
@@ -157,15 +157,15 @@ static int aim_open(struct inode *inode, struct file *filp)
 }
 
 /**
- * aim_close - implements the syscall to close the device
+ * comp_close - implements the syscall to close the device
  * @inode: inode pointer
  * @filp: file pointer
  *
  * This stops the channel within the core.
  */
-static int aim_close(struct inode *inode, struct file *filp)
+static int comp_close(struct inode *inode, struct file *filp)
 {
-	struct aim_channel *c = to_channel(inode->i_cdev);
+	struct comp_channel *c = to_channel(inode->i_cdev);
 
 	mutex_lock(&c->io_mutex);
 	spin_lock(&c->unlink);
@@ -182,19 +182,19 @@ static int aim_close(struct inode *inode, struct file *filp)
 }
 
 /**
- * aim_write - implements the syscall to write to the device
+ * comp_write - implements the syscall to write to the device
  * @filp: file pointer
  * @buf: pointer to user buffer
  * @count: number of bytes to write
  * @offset: offset from where to start writing
  */
-static ssize_t aim_write(struct file *filp, const char __user *buf,
-			 size_t count, loff_t *offset)
+static ssize_t comp_write(struct file *filp, const char __user *buf,
+			  size_t count, loff_t *offset)
 {
 	int ret;
 	size_t to_copy, left;
 	struct mbo *mbo = NULL;
-	struct aim_channel *c = filp->private_data;
+	struct comp_channel *c = filp->private_data;
 
 	mutex_lock(&c->io_mutex);
 	while (c->dev && !ch_get_mbo(c, &mbo)) {
@@ -236,18 +236,18 @@ static ssize_t aim_write(struct file *filp, const char __user *buf,
 }
 
 /**
- * aim_read - implements the syscall to read from the device
+ * comp_read - implements the syscall to read from the device
  * @filp: file pointer
  * @buf: pointer to user buffer
  * @count: number of bytes to read
  * @offset: offset from where to start reading
  */
 static ssize_t
-aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
+comp_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
 {
 	size_t to_copy, not_copied, copied;
 	struct mbo *mbo;
-	struct aim_channel *c = filp->private_data;
+	struct comp_channel *c = filp->private_data;
 
 	mutex_lock(&c->io_mutex);
 	while (c->dev && !kfifo_peek(&c->fifo, &mbo)) {
@@ -287,9 +287,9 @@ static ssize_t aim_write(struct file *filp, const char __user *buf,
 	return copied;
 }
 
-static unsigned int aim_poll(struct file *filp, poll_table *wait)
+static unsigned int comp_poll(struct file *filp, poll_table *wait)
 {
-	struct aim_channel *c = filp->private_data;
+	struct comp_channel *c = filp->private_data;
 	unsigned int mask = 0;
 
 	poll_wait(filp, &c->wq, wait);
@@ -309,24 +309,24 @@ static unsigned int aim_poll(struct file *filp, poll_table *wait)
  */
 static const struct file_operations channel_fops = {
 	.owner = THIS_MODULE,
-	.read = aim_read,
-	.write = aim_write,
-	.open = aim_open,
-	.release = aim_close,
-	.poll = aim_poll,
+	.read = comp_read,
+	.write = comp_write,
+	.open = comp_open,
+	.release = comp_close,
+	.poll = comp_poll,
 };
 
 /**
- * aim_disconnect_channel - disconnect a channel
+ * comp_disconnect_channel - disconnect a channel
  * @iface: pointer to interface instance
  * @channel_id: channel index
  *
  * This frees allocated memory and removes the cdev that represents this
  * channel in user space.
  */
-static int aim_disconnect_channel(struct most_interface *iface, int channel_id)
+static int comp_disconnect_channel(struct most_interface *iface, int channel_id)
 {
-	struct aim_channel *c;
+	struct comp_channel *c;
 
 	if (!iface) {
 		pr_info("Bad interface pointer\n");
@@ -354,15 +354,15 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id)
 }
 
 /**
- * aim_rx_completion - completion handler for rx channels
+ * comp_rx_completion - completion handler for rx channels
  * @mbo: pointer to buffer object that has completed
  *
  * This searches for the channel linked to this MBO and stores it in the local
  * fifo buffer.
  */
-static int aim_rx_completion(struct mbo *mbo)
+static int comp_rx_completion(struct mbo *mbo)
 {
-	struct aim_channel *c;
+	struct comp_channel *c;
 
 	if (!mbo)
 		return -EINVAL;
@@ -387,15 +387,15 @@ static int aim_rx_completion(struct mbo *mbo)
 }
 
 /**
- * aim_tx_completion - completion handler for tx channels
+ * comp_tx_completion - completion handler for tx channels
  * @iface: pointer to interface instance
  * @channel_id: channel index/ID
  *
  * This wakes sleeping processes in the wait-queue.
  */
-static int aim_tx_completion(struct most_interface *iface, int channel_id)
+static int comp_tx_completion(struct most_interface *iface, int channel_id)
 {
-	struct aim_channel *c;
+	struct comp_channel *c;
 
 	if (!iface) {
 		pr_info("Bad interface pointer\n");
@@ -414,7 +414,7 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id)
 }
 
 /**
- * aim_probe - probe function of the driver module
+ * comp_probe - probe function of the driver module
  * @iface: pointer to interface instance
  * @channel_id: channel index/ID
  * @cfg: pointer to actual channel configuration
@@ -425,17 +425,16 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id)
  *
  * Returns 0 on success or error code otherwise.
  */
-static int aim_probe(struct most_interface *iface, int channel_id,
-		     struct most_channel_config *cfg,
-		     char *name)
+static int comp_probe(struct most_interface *iface, int channel_id,
+		      struct most_channel_config *cfg, char *name)
 {
-	struct aim_channel *c;
+	struct comp_channel *c;
 	unsigned long cl_flags;
 	int retval;
 	int current_minor;
 
 	if ((!iface) || (!cfg) || (!name)) {
-		pr_info("Probing AIM with bad arguments");
+		pr_info("Probing component with bad arguments");
 		return -EINVAL;
 	}
 	c = get_channel(iface, channel_id);
@@ -472,7 +471,7 @@ static int aim_probe(struct most_interface *iface, int channel_id,
 	spin_lock_irqsave(&ch_list_lock, cl_flags);
 	list_add_tail(&c->list, &channel_list);
 	spin_unlock_irqrestore(&ch_list_lock, cl_flags);
-	c->dev = device_create(aim_class,
+	c->dev = device_create(comp_class,
 				     NULL,
 				     c->devno,
 				     NULL,
@@ -497,12 +496,12 @@ static int aim_probe(struct most_interface *iface, int channel_id,
 	return retval;
 }
 
-static struct most_aim cdev_aim = {
-	.name = "aim_cdev",
-	.probe_channel = aim_probe,
-	.disconnect_channel = aim_disconnect_channel,
-	.rx_completion = aim_rx_completion,
-	.tx_completion = aim_tx_completion,
+static struct core_component cdev_comp = {
+	.name = "cdev",
+	.probe_channel = comp_probe,
+	.disconnect_channel = comp_disconnect_channel,
+	.rx_completion = comp_rx_completion,
+	.tx_completion = comp_tx_completion,
 };
 
 static int __init mod_init(void)
@@ -515,26 +514,26 @@ static int __init mod_init(void)
 	spin_lock_init(&ch_list_lock);
 	ida_init(&minor_id);
 
-	err = alloc_chrdev_region(&aim_devno, 0, 50, "cdev");
+	err = alloc_chrdev_region(&comp_devno, 0, 50, "cdev");
 	if (err < 0)
 		goto dest_ida;
-	major = MAJOR(aim_devno);
+	major = MAJOR(comp_devno);
 
-	aim_class = class_create(THIS_MODULE, "most_cdev_aim");
-	if (IS_ERR(aim_class)) {
+	comp_class = class_create(THIS_MODULE, "most_cdev_comp");
+	if (IS_ERR(comp_class)) {
 		pr_err("no udev support\n");
-		err = PTR_ERR(aim_class);
+		err = PTR_ERR(comp_class);
 		goto free_cdev;
 	}
-	err = most_register_aim(&cdev_aim);
+	err = most_register_component(&cdev_comp);
 	if (err)
 		goto dest_class;
 	return 0;
 
 dest_class:
-	class_destroy(aim_class);
+	class_destroy(comp_class);
 free_cdev:
-	unregister_chrdev_region(aim_devno, 1);
+	unregister_chrdev_region(comp_devno, 1);
 dest_ida:
 	ida_destroy(&minor_id);
 	return err;
@@ -542,18 +541,18 @@ static int __init mod_init(void)
 
 static void __exit mod_exit(void)
 {
-	struct aim_channel *c, *tmp;
+	struct comp_channel *c, *tmp;
 
 	pr_info("exit module\n");
 
-	most_deregister_aim(&cdev_aim);
+	most_deregister_component(&cdev_comp);
 
 	list_for_each_entry_safe(c, tmp, &channel_list, list) {
 		destroy_cdev(c);
 		destroy_channel(c);
 	}
-	class_destroy(aim_class);
-	unregister_chrdev_region(aim_devno, 1);
+	class_destroy(comp_class);
+	unregister_chrdev_region(comp_devno, 1);
 	ida_destroy(&minor_id);
 }
 
@@ -561,4 +560,4 @@ static void __exit mod_exit(void)
 module_exit(mod_exit);
 MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("character device AIM for mostcore");
+MODULE_DESCRIPTION("character device component for mostcore");
diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 50b57de..7961690 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -40,13 +40,13 @@
 	struct device_driver drv;
 	struct bus_type bus;
 	struct class *class;
-	struct list_head mod_list;
+	struct list_head comp_list;
 } mc;
 
 #define to_driver(d) container_of(d, struct mostcore, drv);
 
 struct pipe {
-	struct most_aim *aim;
+	struct core_component *comp;
 	int refs;
 	int num_buffers;
 };
@@ -545,17 +545,13 @@ static ssize_t interface_show(struct device *dev,
 	NULL,
 };
 
-
-/*		     ___     ___
- *		     ___A I M___
- */
-static struct most_aim *match_module(char *name)
+static struct core_component *match_component(char *name)
 {
-	struct most_aim *aim;
+	struct core_component *comp;
 
-	list_for_each_entry(aim, &mc.mod_list, list) {
-		if (!strcmp(aim->name, name))
-			return aim;
+	list_for_each_entry(comp, &mc.comp_list, list) {
+		if (!strcmp(comp->name, name))
+			return comp;
 	}
 	return NULL;
 }
@@ -568,19 +564,19 @@ int print_links(struct device *dev, void *data)
 	struct most_interface *iface = to_most_interface(dev);
 
 	list_for_each_entry(c, &iface->p->channel_list, list) {
-		if (c->pipe0.aim) {
+		if (c->pipe0.comp) {
 			offs += snprintf(buf + offs,
 					 PAGE_SIZE - offs,
 					 "%s:%s:%s\n",
-					 c->pipe0.aim->name,
+					 c->pipe0.comp->name,
 					 dev_name(&iface->dev),
 					 dev_name(&c->dev));
 		}
-		if (c->pipe1.aim) {
+		if (c->pipe1.comp) {
 			offs += snprintf(buf + offs,
 					 PAGE_SIZE - offs,
 					 "%s:%s:%s\n",
-					 c->pipe1.aim->name,
+					 c->pipe1.comp->name,
 					 dev_name(&iface->dev),
 					 dev_name(&c->dev));
 		}
@@ -594,14 +590,14 @@ static ssize_t links_show(struct device_driver *drv, char *buf)
 	return strlen(buf);
 }
 
-static ssize_t modules_show(struct device_driver *drv, char *buf)
+static ssize_t components_show(struct device_driver *drv, char *buf)
 {
-	struct most_aim *aim;
+	struct core_component *comp;
 	int offs = 0;
 
-	list_for_each_entry(aim, &mc.mod_list, list) {
+	list_for_each_entry(comp, &mc.comp_list, list) {
 		offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s\n",
-				 aim->name);
+				 comp->name);
 	}
 	return offs;
 }
@@ -678,24 +674,24 @@ static struct most_channel *get_channel(char *mdev, char *mdev_ch)
 	return NULL;
 }
 
-static int link_channel_to_aim(struct most_channel *c, struct most_aim *aim,
-			       char *aim_param)
+static int link_channel_to_component(struct most_channel *c,
+				     struct core_component *comp,
+				     char *comp_param)
 {
 	int ret;
-	struct most_aim **aim_ptr;
+	struct core_component **comp_ptr;
 
-	if (!c->pipe0.aim)
-		aim_ptr = &c->pipe0.aim;
-	else if (!c->pipe1.aim)
-		aim_ptr = &c->pipe1.aim;
+	if (!c->pipe0.comp)
+		comp_ptr = &c->pipe0.comp;
+	else if (!c->pipe1.comp)
+		comp_ptr = &c->pipe1.comp;
 	else
 		return -ENOSPC;
 
-	*aim_ptr = aim;
-	ret = aim->probe_channel(c->iface, c->channel_id,
-				 &c->cfg, aim_param);
+	*comp_ptr = comp;
+	ret = comp->probe_channel(c->iface, c->channel_id, &c->cfg, comp_param);
 	if (ret) {
-		*aim_ptr = NULL;
+		*comp_ptr = NULL;
 		return ret;
 	}
 
@@ -704,18 +700,18 @@ static int link_channel_to_aim(struct most_channel *c, struct most_aim *aim,
 
 /**
  * add_link_store - store() function for add_link attribute
- * @aim_obj: pointer to AIM object
+ * @comp_obj: pointer to component object
  * @attr: its attributes
  * @buf: buffer
  * @len: buffer length
  *
  * This parses the string given by buf and splits it into
  * three substrings. Note: third substring is optional. In case a cdev
- * AIM is loaded the optional 3rd substring will make up the name of
+ * component is loaded the optional 3rd substring will make up the name of
  * device node in the /dev directory. If omitted, the device node will
  * inherit the channel's name within sysfs.
  *
- * Searches for a pair of device and channel and probes the AIM
+ * Searches for a pair of device and channel and probes the component
  *
  * Example:
  * (1) echo "mdev0:ch6:my_rxchannel" >add_link
@@ -729,33 +725,34 @@ static ssize_t add_link_store(struct device_driver *drv,
 			      size_t len)
 {
 	struct most_channel *c;
-	struct most_aim *aim;
+	struct core_component *comp;
 	char buffer[STRING_SIZE];
 	char *mdev;
 	char *mdev_ch;
-	char *aim_name;
-	char *aim_param;
+	char *comp_name;
+	char *comp_param;
 	char devnod_buf[STRING_SIZE];
 	int ret;
 	size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
 
 	strlcpy(buffer, buf, max_len);
 
-	ret = split_string(buffer, &mdev, &mdev_ch, &aim_name, &aim_param);
+	ret = split_string(buffer, &mdev, &mdev_ch, &comp_name,
+			   &comp_param);
 	if (ret)
 		return ret;
-	aim = match_module(aim_name);
-	if (!aim_param || *aim_param == 0) {
+	comp = match_component(comp_name);
+	if (!comp_param || *comp_param == 0) {
 		snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev,
 			 mdev_ch);
-		aim_param = devnod_buf;
+		comp_param = devnod_buf;
 	}
 
 	c = get_channel(mdev, mdev_ch);
 	if (!c)
 		return -ENODEV;
 
-	ret = link_channel_to_aim(c, aim, aim_param);
+	ret = link_channel_to_component(c, comp, comp_param);
 	if (ret)
 		return ret;
 
@@ -764,7 +761,7 @@ static ssize_t add_link_store(struct device_driver *drv,
 
 /**
  * remove_link_store - store function for remove_link attribute
- * @aim_obj: pointer to AIM object
+ * @comp_obj: pointer to component object
  * @attr: its attributes
  * @buf: buffer
  * @len: buffer length
@@ -777,53 +774,53 @@ static ssize_t remove_link_store(struct device_driver *drv,
 				 size_t len)
 {
 	struct most_channel *c;
-	struct most_aim *aim;
+	struct core_component *comp;
 	char buffer[STRING_SIZE];
 	char *mdev;
 	char *mdev_ch;
-	char *aim_name;
+	char *comp_name;
 	int ret;
 	size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
 
 	strlcpy(buffer, buf, max_len);
-	ret = split_string(buffer, &mdev, &mdev_ch, &aim_name, NULL);
+	ret = split_string(buffer, &mdev, &mdev_ch, &comp_name, NULL);
 	if (ret)
 		return ret;
-	aim = match_module(aim_name);
+	comp = match_component(comp_name);
 	c = get_channel(mdev, mdev_ch);
 	if (!c)
 		return -ENODEV;
 
-	if (aim->disconnect_channel(c->iface, c->channel_id))
+	if (comp->disconnect_channel(c->iface, c->channel_id))
 		return -EIO;
-	if (c->pipe0.aim == aim)
-		c->pipe0.aim = NULL;
-	if (c->pipe1.aim == aim)
-		c->pipe1.aim = NULL;
+	if (c->pipe0.comp == comp)
+		c->pipe0.comp = NULL;
+	if (c->pipe1.comp == comp)
+		c->pipe1.comp = NULL;
 	return len;
 }
 
 #define DRV_ATTR(_name)  &driver_attr_##_name.attr
 
 static DRIVER_ATTR_RO(links);
-static DRIVER_ATTR_RO(modules);
+static DRIVER_ATTR_RO(components);
 static DRIVER_ATTR_WO(add_link);
 static DRIVER_ATTR_WO(remove_link);
 
-static struct attribute *module_attrs[] = {
+static struct attribute *mc_attrs[] = {
 	DRV_ATTR(links),
-	DRV_ATTR(modules),
+	DRV_ATTR(components),
 	DRV_ATTR(add_link),
 	DRV_ATTR(remove_link),
 	NULL,
 };
 
-static struct attribute_group module_attr_group = {
-	.attrs = module_attrs,
+static struct attribute_group mc_attr_group = {
+	.attrs = mc_attrs,
 };
 
-static const struct attribute_group *module_attr_groups[] = {
-	&module_attr_group,
+static const struct attribute_group *mc_attr_groups[] = {
+	&mc_attr_group,
 	NULL,
 };
 /*		     ___       ___
@@ -927,7 +924,7 @@ static int run_enqueue_thread(struct most_channel *c, int channel_id)
  *
  * In case the MBO belongs to a channel that recently has been
  * poisoned, the MBO is scheduled to be trashed.
- * Calls the completion handler of an attached AIM.
+ * Calls the completion handler of an attached component.
  */
 static void arm_mbo(struct mbo *mbo)
 {
@@ -947,11 +944,11 @@ static void arm_mbo(struct mbo *mbo)
 	list_add_tail(&mbo->list, &c->fifo);
 	spin_unlock_irqrestore(&c->fifo_lock, flags);
 
-	if (c->pipe0.refs && c->pipe0.aim->tx_completion)
-		c->pipe0.aim->tx_completion(c->iface, c->channel_id);
+	if (c->pipe0.refs && c->pipe0.comp->tx_completion)
+		c->pipe0.comp->tx_completion(c->iface, c->channel_id);
 
-	if (c->pipe1.refs && c->pipe1.aim->tx_completion)
-		c->pipe1.aim->tx_completion(c->iface, c->channel_id);
+	if (c->pipe1.refs && c->pipe1.comp->tx_completion)
+		c->pipe1.comp->tx_completion(c->iface, c->channel_id);
 }
 
 /**
@@ -1048,7 +1045,8 @@ static void most_write_completion(struct mbo *mbo)
 		arm_mbo(mbo);
 }
 
-int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim)
+int channel_has_mbo(struct most_interface *iface, int id,
+		    struct core_component *comp)
 {
 	struct most_channel *c = iface->p->channel[id];
 	unsigned long flags;
@@ -1058,8 +1056,8 @@ int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim)
 		return -EINVAL;
 
 	if (c->pipe0.refs && c->pipe1.refs &&
-	    ((aim == c->pipe0.aim && c->pipe0.num_buffers <= 0) ||
-	     (aim == c->pipe1.aim && c->pipe1.num_buffers <= 0)))
+	    ((comp == c->pipe0.comp && c->pipe0.num_buffers <= 0) ||
+	     (comp == c->pipe1.comp && c->pipe1.num_buffers <= 0)))
 		return 0;
 
 	spin_lock_irqsave(&c->fifo_lock, flags);
@@ -1078,7 +1076,7 @@ int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim)
  * Returns a pointer to MBO on success or NULL otherwise.
  */
 struct mbo *most_get_mbo(struct most_interface *iface, int id,
-			 struct most_aim *aim)
+			 struct core_component *comp)
 {
 	struct mbo *mbo;
 	struct most_channel *c;
@@ -1090,13 +1088,13 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id,
 		return NULL;
 
 	if (c->pipe0.refs && c->pipe1.refs &&
-	    ((aim == c->pipe0.aim && c->pipe0.num_buffers <= 0) ||
-	     (aim == c->pipe1.aim && c->pipe1.num_buffers <= 0)))
+	    ((comp == c->pipe0.comp && c->pipe0.num_buffers <= 0) ||
+	     (comp == c->pipe1.comp && c->pipe1.num_buffers <= 0)))
 		return NULL;
 
-	if (aim == c->pipe0.aim)
+	if (comp == c->pipe0.comp)
 		num_buffers_ptr = &c->pipe0.num_buffers;
-	else if (aim == c->pipe1.aim)
+	else if (comp == c->pipe1.comp)
 		num_buffers_ptr = &c->pipe1.num_buffers;
 	else
 		num_buffers_ptr = &dummy_num_buffers;
@@ -1141,7 +1139,7 @@ void most_put_mbo(struct mbo *mbo)
  * hardware and copied to the buffer of the MBO.
  *
  * In case the channel has been poisoned it puts the buffer in the trash queue.
- * Otherwise, it passes the buffer to an AIM for further processing.
+ * Otherwise, it passes the buffer to an component for further processing.
  */
 static void most_read_completion(struct mbo *mbo)
 {
@@ -1161,12 +1159,12 @@ static void most_read_completion(struct mbo *mbo)
 	if (atomic_sub_and_test(1, &c->mbo_nq_level))
 		c->is_starving = 1;
 
-	if (c->pipe0.refs && c->pipe0.aim->rx_completion &&
-	    c->pipe0.aim->rx_completion(mbo) == 0)
+	if (c->pipe0.refs && c->pipe0.comp->rx_completion &&
+	    c->pipe0.comp->rx_completion(mbo) == 0)
 		return;
 
-	if (c->pipe1.refs && c->pipe1.aim->rx_completion &&
-	    c->pipe1.aim->rx_completion(mbo) == 0)
+	if (c->pipe1.refs && c->pipe1.comp->rx_completion &&
+	    c->pipe1.comp->rx_completion(mbo) == 0)
 		return;
 
 	most_put_mbo(mbo);
@@ -1183,7 +1181,7 @@ static void most_read_completion(struct mbo *mbo)
  * Returns 0 on success or error code otherwise.
  */
 int most_start_channel(struct most_interface *iface, int id,
-		       struct most_aim *aim)
+		       struct core_component *comp)
 {
 	int num_buffer;
 	int ret;
@@ -1194,7 +1192,7 @@ int most_start_channel(struct most_interface *iface, int id,
 
 	mutex_lock(&c->start_mutex);
 	if (c->pipe0.refs + c->pipe1.refs > 0)
-		goto out; /* already started by other aim */
+		goto out; /* already started by other component */
 
 	if (!try_module_get(iface->mod)) {
 		pr_info("failed to acquire HDM lock\n");
@@ -1233,9 +1231,9 @@ int most_start_channel(struct most_interface *iface, int id,
 	atomic_set(&c->mbo_ref, num_buffer);
 
 out:
-	if (aim == c->pipe0.aim)
+	if (comp == c->pipe0.comp)
 		c->pipe0.refs++;
-	if (aim == c->pipe1.aim)
+	if (comp == c->pipe1.comp)
 		c->pipe1.refs++;
 	mutex_unlock(&c->start_mutex);
 	return 0;
@@ -1253,7 +1251,7 @@ int most_start_channel(struct most_interface *iface, int id,
  * @id: channel ID
  */
 int most_stop_channel(struct most_interface *iface, int id,
-		      struct most_aim *aim)
+		      struct core_component *comp)
 {
 	struct most_channel *c;
 
@@ -1298,9 +1296,9 @@ int most_stop_channel(struct most_interface *iface, int id,
 	c->is_poisoned = false;
 
 out:
-	if (aim == c->pipe0.aim)
+	if (comp == c->pipe0.comp)
 		c->pipe0.refs--;
-	if (aim == c->pipe1.aim)
+	if (comp == c->pipe1.comp)
 		c->pipe1.refs--;
 	mutex_unlock(&c->start_mutex);
 	return 0;
@@ -1308,56 +1306,56 @@ int most_stop_channel(struct most_interface *iface, int id,
 EXPORT_SYMBOL_GPL(most_stop_channel);
 
 /**
- * most_register_aim - registers an AIM (driver) with the core
- * @aim: instance of AIM to be registered
+ * most_register_component - registers an component (driver) with the core
+ * @comp: instance of component to be registered
  */
-int most_register_aim(struct most_aim *aim)
+int most_register_component(struct core_component *comp)
 {
-	if (!aim) {
-		pr_err("Bad driver\n");
+	if (!comp) {
+		pr_err("Bad component\n");
 		return -EINVAL;
 	}
-	list_add_tail(&aim->list, &mc.mod_list);
-	pr_info("registered new application interfacing module %s\n", aim->name);
+	list_add_tail(&comp->list, &mc.comp_list);
+	pr_info("registered new core component %s\n", comp->name);
 	return 0;
 }
-EXPORT_SYMBOL_GPL(most_register_aim);
+EXPORT_SYMBOL_GPL(most_register_component);
 
 static int disconnect_channels(struct device *dev, void *data)
 {
 	struct most_interface *iface;
 	struct most_channel *c, *tmp;
-	struct most_aim *aim = data;
+	struct core_component *comp = data;
 
 	iface = to_most_interface(dev);
 	list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) {
-		if (c->pipe0.aim == aim || c->pipe1.aim == aim)
-			aim->disconnect_channel(c->iface, c->channel_id);
-		if (c->pipe0.aim == aim)
-			c->pipe0.aim = NULL;
-		if (c->pipe1.aim == aim)
-			c->pipe1.aim = NULL;
+		if (c->pipe0.comp == comp || c->pipe1.comp == comp)
+			comp->disconnect_channel(c->iface, c->channel_id);
+		if (c->pipe0.comp == comp)
+			c->pipe0.comp = NULL;
+		if (c->pipe1.comp == comp)
+			c->pipe1.comp = NULL;
 	}
 	return 0;
 }
 
 /**
- * most_deregister_aim - deregisters an AIM (driver) with the core
- * @aim: AIM to be removed
+ * most_deregister_component - deregisters an component (driver) with the core
+ * @comp: component to be removed
  */
-int most_deregister_aim(struct most_aim *aim)
+int most_deregister_component(struct core_component *comp)
 {
-	if (!aim) {
-		pr_err("Bad driver\n");
+	if (!comp) {
+		pr_err("Bad component\n");
 		return -EINVAL;
 	}
 
-	bus_for_each_dev(&mc.bus, NULL, aim, disconnect_channels);
-	list_del(&aim->list);
-	pr_info("deregistering module %s\n", aim->name);
+	bus_for_each_dev(&mc.bus, NULL, comp, disconnect_channels);
+	list_del(&comp->list);
+	pr_info("deregistering component %s\n", comp->name);
 	return 0;
 }
-EXPORT_SYMBOL_GPL(most_deregister_aim);
+EXPORT_SYMBOL_GPL(most_deregister_component);
 
 static void release_interface(struct device *dev)
 {
@@ -1457,7 +1455,7 @@ int most_register_interface(struct most_interface *iface)
 		mutex_init(&c->nq_mutex);
 		list_add_tail(&c->list, &iface->p->channel_list);
 	}
-	pr_info("registered new MOST device mdev%d (%s)\n",
+	pr_info("registered new device mdev%d (%s)\n",
 		id, iface->description);
 	return 0;
 
@@ -1489,17 +1487,17 @@ void most_deregister_interface(struct most_interface *iface)
 	int i;
 	struct most_channel *c;
 
-	pr_info("deregistering MOST device %s (%s)\n", dev_name(&iface->dev), iface->description);
+	pr_info("deregistering device %s (%s)\n", dev_name(&iface->dev), iface->description);
 	for (i = 0; i < iface->num_channels; i++) {
 		c = iface->p->channel[i];
-		if (c->pipe0.aim)
-			c->pipe0.aim->disconnect_channel(c->iface,
+		if (c->pipe0.comp)
+			c->pipe0.comp->disconnect_channel(c->iface,
 							c->channel_id);
-		if (c->pipe1.aim)
-			c->pipe1.aim->disconnect_channel(c->iface,
+		if (c->pipe1.comp)
+			c->pipe1.comp->disconnect_channel(c->iface,
 							c->channel_id);
-		c->pipe0.aim = NULL;
-		c->pipe1.aim = NULL;
+		c->pipe0.comp = NULL;
+		c->pipe1.comp = NULL;
 		list_del(&c->list);
 		device_unregister(&c->dev);
 		kfree(c);
@@ -1567,14 +1565,14 @@ static int __init most_init(void)
 	int err;
 
 	pr_info("init()\n");
-	INIT_LIST_HEAD(&mc.mod_list);
+	INIT_LIST_HEAD(&mc.comp_list);
 	ida_init(&mdev_id);
 
 	mc.bus.name = "most",
 	mc.bus.match = most_match,
-	mc.drv.name = "most_core",
+	mc.drv.name = "core",
 	mc.drv.bus = &mc.bus,
-	mc.drv.groups = module_attr_groups;
+	mc.drv.groups = mc_attr_groups;
 
 	err = bus_register(&mc.bus);
 	if (err) {
@@ -1593,7 +1591,7 @@ static int __init most_init(void)
 		pr_info("Cannot register core driver\n");
 		goto exit_class;
 	}
-	mc.dev.init_name = "most_bus";
+	mc.dev.init_name = "most";
 	mc.dev.release = release_most_sub;
 	if (device_register(&mc.dev)) {
 		err = -ENOMEM;
diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h
index 09fa472..d74276d 100644
--- a/drivers/staging/most/core.h
+++ b/drivers/staging/most/core.h
@@ -268,7 +268,7 @@ struct most_interface {
  * @tx_completion: completion handler for transmitted packets
  * @context: context pointer to be used by mostcore
  */
-struct most_aim {
+struct core_component {
 	struct list_head list;
 	const char *name;
 	int (*probe_channel)(struct most_interface *iface, int channel_idx,
@@ -279,7 +279,6 @@ struct most_aim {
 	int (*tx_completion)(struct most_interface *iface, int channel_idx);
 };
 
-#define to_most_aim(d) container_of(d, struct most_aim, dev)
 /**
  * most_register_interface - Registers instance of the interface.
  * @iface: Pointer to the interface instance description.
@@ -314,16 +313,16 @@ struct most_aim {
  * in wait fifo.
  */
 void most_resume_enqueue(struct most_interface *iface, int channel_idx);
-int most_register_aim(struct most_aim *aim);
-int most_deregister_aim(struct most_aim *aim);
+int most_register_component(struct core_component *comp);
+int most_deregister_component(struct core_component *comp);
 struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx,
-			 struct most_aim *);
+			 struct core_component *comp);
 void most_put_mbo(struct mbo *mbo);
 int channel_has_mbo(struct most_interface *iface, int channel_idx,
-		    struct most_aim *aim);
+		    struct core_component *comp);
 int most_start_channel(struct most_interface *iface, int channel_idx,
-		       struct most_aim *);
+		       struct core_component *comp);
 int most_stop_channel(struct most_interface *iface, int channel_idx,
-		      struct most_aim *);
+		      struct core_component *comp);
 
 #endif /* MOST_CORE_H_ */
diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c
index 194fe63..01b36ad 100644
--- a/drivers/staging/most/net/net.c
+++ b/drivers/staging/most/net/net.c
@@ -1,5 +1,5 @@
 /*
- * Networking AIM - Networking Application Interface Module for MostCore
+ * Networking component - Networking Application Interface Module for MostCore
  *
  * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
  *
@@ -74,7 +74,7 @@ struct net_dev_context {
 static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
 static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */
 static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */
-static struct most_aim aim;
+static struct core_component comp;
 
 static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
 {
@@ -184,15 +184,15 @@ static int most_nd_open(struct net_device *dev)
 
 	mutex_lock(&probe_disc_mt);
 
-	if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) {
+	if (most_start_channel(nd->iface, nd->rx.ch_id, &comp)) {
 		netdev_err(dev, "most_start_channel() failed\n");
 		ret = -EBUSY;
 		goto unlock;
 	}
 
-	if (most_start_channel(nd->iface, nd->tx.ch_id, &aim)) {
+	if (most_start_channel(nd->iface, nd->tx.ch_id, &comp)) {
 		netdev_err(dev, "most_start_channel() failed\n");
-		most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
+		most_stop_channel(nd->iface, nd->rx.ch_id, &comp);
 		ret = -EBUSY;
 		goto unlock;
 	}
@@ -218,8 +218,8 @@ static int most_nd_stop(struct net_device *dev)
 	netif_stop_queue(dev);
 	if (nd->iface->request_netinfo)
 		nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, NULL);
-	most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
-	most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
+	most_stop_channel(nd->iface, nd->rx.ch_id, &comp);
+	most_stop_channel(nd->iface, nd->tx.ch_id, &comp);
 
 	return 0;
 }
@@ -231,7 +231,7 @@ static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb,
 	struct mbo *mbo;
 	int ret;
 
-	mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim);
+	mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &comp);
 
 	if (!mbo) {
 		netif_stop_queue(dev);
@@ -296,9 +296,8 @@ static struct net_dev_context *get_net_dev_hold(struct most_interface *iface)
 	return nd;
 }
 
-static int aim_probe_channel(struct most_interface *iface, int channel_idx,
-			     struct most_channel_config *ccfg,
-			     char *name)
+static int comp_probe_channel(struct most_interface *iface, int channel_idx,
+			      struct most_channel_config *ccfg, char *name)
 {
 	struct net_dev_context *nd;
 	struct net_dev_channel *ch;
@@ -353,8 +352,8 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
 	return ret;
 }
 
-static int aim_disconnect_channel(struct most_interface *iface,
-				  int channel_idx)
+static int comp_disconnect_channel(struct most_interface *iface,
+				   int channel_idx)
 {
 	struct net_dev_context *nd;
 	struct net_dev_channel *ch;
@@ -400,8 +399,8 @@ static int aim_disconnect_channel(struct most_interface *iface,
 	return ret;
 }
 
-static int aim_resume_tx_channel(struct most_interface *iface,
-				 int channel_idx)
+static int comp_resume_tx_channel(struct most_interface *iface,
+				  int channel_idx)
 {
 	struct net_dev_context *nd;
 
@@ -419,7 +418,7 @@ static int aim_resume_tx_channel(struct most_interface *iface,
 	return 0;
 }
 
-static int aim_rx_data(struct mbo *mbo)
+static int comp_rx_data(struct mbo *mbo)
 {
 	const u32 zero = 0;
 	struct net_dev_context *nd;
@@ -501,24 +500,24 @@ static int aim_rx_data(struct mbo *mbo)
 	return ret;
 }
 
-static struct most_aim aim = {
-	.name = "aim_networking",
-	.probe_channel = aim_probe_channel,
-	.disconnect_channel = aim_disconnect_channel,
-	.tx_completion = aim_resume_tx_channel,
-	.rx_completion = aim_rx_data,
+static struct core_component comp = {
+	.name = "net",
+	.probe_channel = comp_probe_channel,
+	.disconnect_channel = comp_disconnect_channel,
+	.tx_completion = comp_resume_tx_channel,
+	.rx_completion = comp_rx_data,
 };
 
 static int __init most_net_init(void)
 {
 	spin_lock_init(&list_lock);
 	mutex_init(&probe_disc_mt);
-	return most_register_aim(&aim);
+	return most_register_component(&comp);
 }
 
 static void __exit most_net_exit(void)
 {
-	most_deregister_aim(&aim);
+	most_deregister_component(&comp);
 }
 
 /**
diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c
index 4c3397a..a409cd5 100644
--- a/drivers/staging/most/sound/sound.c
+++ b/drivers/staging/most/sound/sound.c
@@ -24,10 +24,10 @@
 #include <linux/kthread.h>
 #include <most/core.h>
 
-#define DRIVER_NAME "aim_sound"
+#define DRIVER_NAME "sound"
 
 static struct list_head dev_list;
-static struct most_aim audio_aim;
+static struct core_component snd_component;
 
 /**
  * struct channel - private structure to keep channel specific data
@@ -240,7 +240,7 @@ static int playback_thread(void *data)
 			kthread_should_stop() ||
 			(channel->is_stream_running &&
 			 (mbo = most_get_mbo(channel->iface, channel->id,
-					     &audio_aim))));
+					     &snd_component))));
 		if (!mbo)
 			continue;
 
@@ -283,7 +283,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
 		}
 	}
 
-	if (most_start_channel(channel->iface, channel->id, &audio_aim)) {
+	if (most_start_channel(channel->iface, channel->id, &snd_component)) {
 		pr_err("most_start_channel() failed!\n");
 		if (cfg->direction == MOST_CH_TX)
 			kthread_stop(channel->playback_task);
@@ -310,7 +310,7 @@ static int pcm_close(struct snd_pcm_substream *substream)
 
 	if (channel->cfg->direction == MOST_CH_TX)
 		kthread_stop(channel->playback_task);
-	most_stop_channel(channel->iface, channel->id, &audio_aim);
+	most_stop_channel(channel->iface, channel->id, &snd_component);
 
 	return 0;
 }
@@ -723,9 +723,9 @@ static int audio_tx_completion(struct most_interface *iface, int channel_id)
 }
 
 /**
- * Initialization of the struct most_aim
+ * Initialization of the struct core_component
  */
-static struct most_aim audio_aim = {
+static struct core_component snd_component = {
 	.name = DRIVER_NAME,
 	.probe_channel = audio_probe_channel,
 	.disconnect_channel = audio_disconnect_channel,
@@ -739,7 +739,7 @@ static int __init audio_init(void)
 
 	INIT_LIST_HEAD(&dev_list);
 
-	return most_register_aim(&audio_aim);
+	return most_register_component(&snd_component);
 }
 
 static void __exit audio_exit(void)
@@ -753,7 +753,7 @@ static void __exit audio_exit(void)
 		snd_card_free(channel->card);
 	}
 
-	most_deregister_aim(&audio_aim);
+	most_deregister_component(&snd_component);
 }
 
 module_init(audio_init);
diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c
index 5b704d9..dff6f3d 100644
--- a/drivers/staging/most/video/video.c
+++ b/drivers/staging/most/video/video.c
@@ -1,5 +1,5 @@
 /*
- * V4L2 AIM - V4L2 Application Interface Module for MostCore
+ * V4L2 Component - V4L2 Application Interface Module for MostCore
  *
  * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
  *
@@ -29,9 +29,9 @@
 
 #include <most/core.h>
 
-#define V4L2_AIM_MAX_INPUT  1
+#define V4L2_CMP_MAX_INPUT  1
 
-static struct most_aim aim_info;
+static struct core_component comp_info;
 
 struct most_video_dev {
 	struct most_interface *iface;
@@ -52,7 +52,7 @@ struct most_video_dev {
 	wait_queue_head_t wait_data;
 };
 
-struct aim_fh {
+struct comp_fh {
 	/* must be the first field of this struct! */
 	struct v4l2_fh fh;
 	struct most_video_dev *mdev;
@@ -72,14 +72,14 @@ static inline struct mbo *get_top_mbo(struct most_video_dev *mdev)
 	return list_first_entry(&mdev->pending_mbos, struct mbo, list);
 }
 
-static int aim_vdev_open(struct file *filp)
+static int comp_vdev_open(struct file *filp)
 {
 	int ret;
 	struct video_device *vdev = video_devdata(filp);
 	struct most_video_dev *mdev = video_drvdata(filp);
-	struct aim_fh *fh;
+	struct comp_fh *fh;
 
-	v4l2_info(&mdev->v4l2_dev, "aim_vdev_open()\n");
+	v4l2_info(&mdev->v4l2_dev, "comp_vdev_open()\n");
 
 	switch (vdev->vfl_type) {
 	case VFL_TYPE_GRABBER:
@@ -104,7 +104,7 @@ static int aim_vdev_open(struct file *filp)
 
 	v4l2_fh_add(&fh->fh);
 
-	ret = most_start_channel(mdev->iface, mdev->ch_idx, &aim_info);
+	ret = most_start_channel(mdev->iface, mdev->ch_idx, &comp_info);
 	if (ret) {
 		v4l2_err(&mdev->v4l2_dev, "most_start_channel() failed\n");
 		goto err_rm;
@@ -122,13 +122,13 @@ static int aim_vdev_open(struct file *filp)
 	return ret;
 }
 
-static int aim_vdev_close(struct file *filp)
+static int comp_vdev_close(struct file *filp)
 {
-	struct aim_fh *fh = filp->private_data;
+	struct comp_fh *fh = filp->private_data;
 	struct most_video_dev *mdev = fh->mdev;
 	struct mbo *mbo, *tmp;
 
-	v4l2_info(&mdev->v4l2_dev, "aim_vdev_close()\n");
+	v4l2_info(&mdev->v4l2_dev, "comp_vdev_close()\n");
 
 	/*
 	 * We need to put MBOs back before we call most_stop_channel()
@@ -148,7 +148,7 @@ static int aim_vdev_close(struct file *filp)
 		spin_lock_irq(&mdev->list_lock);
 	}
 	spin_unlock_irq(&mdev->list_lock);
-	most_stop_channel(mdev->iface, mdev->ch_idx, &aim_info);
+	most_stop_channel(mdev->iface, mdev->ch_idx, &comp_info);
 	mdev->mute = false;
 
 	v4l2_fh_del(&fh->fh);
@@ -159,10 +159,10 @@ static int aim_vdev_close(struct file *filp)
 	return 0;
 }
 
-static ssize_t aim_vdev_read(struct file *filp, char __user *buf,
-			     size_t count, loff_t *pos)
+static ssize_t comp_vdev_read(struct file *filp, char __user *buf,
+			      size_t count, loff_t *pos)
 {
-	struct aim_fh *fh = filp->private_data;
+	struct comp_fh *fh = filp->private_data;
 	struct most_video_dev *mdev = fh->mdev;
 	int ret = 0;
 
@@ -209,9 +209,9 @@ static ssize_t aim_vdev_read(struct file *filp, char __user *buf,
 	return ret;
 }
 
-static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait)
+static unsigned int comp_vdev_poll(struct file *filp, poll_table *wait)
 {
-	struct aim_fh *fh = filp->private_data;
+	struct comp_fh *fh = filp->private_data;
 	struct most_video_dev *mdev = fh->mdev;
 	unsigned int mask = 0;
 
@@ -224,7 +224,7 @@ static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait)
 	return mask;
 }
 
-static void aim_set_format_struct(struct v4l2_format *f)
+static void comp_set_format_struct(struct v4l2_format *f)
 {
 	f->fmt.pix.width = 8;
 	f->fmt.pix.height = 8;
@@ -236,8 +236,8 @@ static void aim_set_format_struct(struct v4l2_format *f)
 	f->fmt.pix.priv = 0;
 }
 
-static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd,
-			  struct v4l2_format *format)
+static int comp_set_format(struct most_video_dev *mdev, unsigned int cmd,
+			   struct v4l2_format *format)
 {
 	if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG)
 		return -EINVAL;
@@ -245,7 +245,7 @@ static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd,
 	if (cmd == VIDIOC_TRY_FMT)
 		return 0;
 
-	aim_set_format_struct(format);
+	comp_set_format_struct(format);
 
 	return 0;
 }
@@ -253,12 +253,12 @@ static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd,
 static int vidioc_querycap(struct file *file, void *priv,
 			   struct v4l2_capability *cap)
 {
-	struct aim_fh *fh = priv;
+	struct comp_fh *fh = priv;
 	struct most_video_dev *mdev = fh->mdev;
 
 	v4l2_info(&mdev->v4l2_dev, "vidioc_querycap()\n");
 
-	strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver));
+	strlcpy(cap->driver, "v4l2_component", sizeof(cap->driver));
 	strlcpy(cap->card, "MOST", sizeof(cap->card));
 	snprintf(cap->bus_info, sizeof(cap->bus_info),
 		 "%s", mdev->iface->description);
@@ -273,7 +273,7 @@ static int vidioc_querycap(struct file *file, void *priv,
 static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
 				   struct v4l2_fmtdesc *f)
 {
-	struct aim_fh *fh = priv;
+	struct comp_fh *fh = priv;
 	struct most_video_dev *mdev = fh->mdev;
 
 	v4l2_info(&mdev->v4l2_dev, "vidioc_enum_fmt_vid_cap() %d\n", f->index);
@@ -292,36 +292,36 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	struct aim_fh *fh = priv;
+	struct comp_fh *fh = priv;
 	struct most_video_dev *mdev = fh->mdev;
 
 	v4l2_info(&mdev->v4l2_dev, "vidioc_g_fmt_vid_cap()\n");
 
-	aim_set_format_struct(f);
+	comp_set_format_struct(f);
 	return 0;
 }
 
 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 				  struct v4l2_format *f)
 {
-	struct aim_fh *fh = priv;
+	struct comp_fh *fh = priv;
 	struct most_video_dev *mdev = fh->mdev;
 
-	return aim_set_format(mdev, VIDIOC_TRY_FMT, f);
+	return comp_set_format(mdev, VIDIOC_TRY_FMT, f);
 }
 
 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	struct aim_fh *fh = priv;
+	struct comp_fh *fh = priv;
 	struct most_video_dev *mdev = fh->mdev;
 
-	return aim_set_format(mdev, VIDIOC_S_FMT, f);
+	return comp_set_format(mdev, VIDIOC_S_FMT, f);
 }
 
 static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
 {
-	struct aim_fh *fh = priv;
+	struct comp_fh *fh = priv;
 	struct most_video_dev *mdev = fh->mdev;
 
 	v4l2_info(&mdev->v4l2_dev, "vidioc_g_std()\n");
@@ -333,10 +333,10 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
 static int vidioc_enum_input(struct file *file, void *priv,
 			     struct v4l2_input *input)
 {
-	struct aim_fh *fh = priv;
+	struct comp_fh *fh = priv;
 	struct most_video_dev *mdev = fh->mdev;
 
-	if (input->index >= V4L2_AIM_MAX_INPUT)
+	if (input->index >= V4L2_CMP_MAX_INPUT)
 		return -EINVAL;
 
 	strcpy(input->name, "MOST Video");
@@ -350,7 +350,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
 
 static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
 {
-	struct aim_fh *fh = priv;
+	struct comp_fh *fh = priv;
 	struct most_video_dev *mdev = fh->mdev;
 	*i = mdev->ctrl_input;
 	return 0;
@@ -358,23 +358,23 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
 
 static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
 {
-	struct aim_fh *fh = priv;
+	struct comp_fh *fh = priv;
 	struct most_video_dev *mdev = fh->mdev;
 
 	v4l2_info(&mdev->v4l2_dev, "vidioc_s_input(%d)\n", index);
 
-	if (index >= V4L2_AIM_MAX_INPUT)
+	if (index >= V4L2_CMP_MAX_INPUT)
 		return -EINVAL;
 	mdev->ctrl_input = index;
 	return 0;
 }
 
-static const struct v4l2_file_operations aim_fops = {
+static const struct v4l2_file_operations comp_fops = {
 	.owner      = THIS_MODULE,
-	.open       = aim_vdev_open,
-	.release    = aim_vdev_close,
-	.read       = aim_vdev_read,
-	.poll       = aim_vdev_poll,
+	.open       = comp_vdev_open,
+	.release    = comp_vdev_close,
+	.read       = comp_vdev_read,
+	.poll       = comp_vdev_poll,
 	.unlocked_ioctl = video_ioctl2,
 };
 
@@ -390,8 +390,8 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
 	.vidioc_s_input             = vidioc_s_input,
 };
 
-static const struct video_device aim_videodev_template = {
-	.fops = &aim_fops,
+static const struct video_device comp_videodev_template = {
+	.fops = &comp_fops,
 	.release = video_device_release,
 	.ioctl_ops = &video_ioctl_ops,
 	.tvnorms = V4L2_STD_UNKNOWN,
@@ -399,7 +399,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
 
 /**************************************************************************/
 
-static struct most_video_dev *get_aim_dev(
+static struct most_video_dev *get_comp_dev(
 	struct most_interface *iface, int channel_idx)
 {
 	struct most_video_dev *mdev;
@@ -416,11 +416,11 @@ static struct most_video_dev *get_aim_dev(
 	return NULL;
 }
 
-static int aim_rx_data(struct mbo *mbo)
+static int comp_rx_data(struct mbo *mbo)
 {
 	unsigned long flags;
 	struct most_video_dev *mdev =
-		get_aim_dev(mbo->ifp, mbo->hdm_channel_id);
+		get_comp_dev(mbo->ifp, mbo->hdm_channel_id);
 
 	if (!mdev)
 		return -EIO;
@@ -437,11 +437,11 @@ static int aim_rx_data(struct mbo *mbo)
 	return 0;
 }
 
-static int aim_register_videodev(struct most_video_dev *mdev)
+static int comp_register_videodev(struct most_video_dev *mdev)
 {
 	int ret;
 
-	v4l2_info(&mdev->v4l2_dev, "aim_register_videodev()\n");
+	v4l2_info(&mdev->v4l2_dev, "comp_register_videodev()\n");
 
 	init_waitqueue_head(&mdev->wait_data);
 
@@ -451,7 +451,7 @@ static int aim_register_videodev(struct most_video_dev *mdev)
 		return -ENOMEM;
 
 	/* Fill the video capture device struct */
-	*mdev->vdev = aim_videodev_template;
+	*mdev->vdev = comp_videodev_template;
 	mdev->vdev->v4l2_dev = &mdev->v4l2_dev;
 	mdev->vdev->lock = &mdev->lock;
 	snprintf(mdev->vdev->name, sizeof(mdev->vdev->name), "MOST: %s",
@@ -469,14 +469,14 @@ static int aim_register_videodev(struct most_video_dev *mdev)
 	return ret;
 }
 
-static void aim_unregister_videodev(struct most_video_dev *mdev)
+static void comp_unregister_videodev(struct most_video_dev *mdev)
 {
-	v4l2_info(&mdev->v4l2_dev, "aim_unregister_videodev()\n");
+	v4l2_info(&mdev->v4l2_dev, "comp_unregister_videodev()\n");
 
 	video_unregister_device(mdev->vdev);
 }
 
-static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev)
+static void comp_v4l2_dev_release(struct v4l2_device *v4l2_dev)
 {
 	struct most_video_dev *mdev =
 		container_of(v4l2_dev, struct most_video_dev, v4l2_dev);
@@ -485,14 +485,13 @@ static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev)
 	kfree(mdev);
 }
 
-static int aim_probe_channel(struct most_interface *iface, int channel_idx,
-			     struct most_channel_config *ccfg,
-			     char *name)
+static int comp_probe_channel(struct most_interface *iface, int channel_idx,
+			      struct most_channel_config *ccfg, char *name)
 {
 	int ret;
-	struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
+	struct most_video_dev *mdev = get_comp_dev(iface, channel_idx);
 
-	pr_info("aim_probe_channel(%s)\n", name);
+	pr_info("comp_probe_channel(%s)\n", name);
 
 	if (mdev) {
 		pr_err("channel already linked\n");
@@ -520,7 +519,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
 	INIT_LIST_HEAD(&mdev->pending_mbos);
 	mdev->iface = iface;
 	mdev->ch_idx = channel_idx;
-	mdev->v4l2_dev.release = aim_v4l2_dev_release;
+	mdev->v4l2_dev.release = comp_v4l2_dev_release;
 
 	/* Create the v4l2_device */
 	strlcpy(mdev->v4l2_dev.name, name, sizeof(mdev->v4l2_dev.name));
@@ -531,14 +530,14 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
 		return ret;
 	}
 
-	ret = aim_register_videodev(mdev);
+	ret = comp_register_videodev(mdev);
 	if (ret)
 		goto err_unreg;
 
 	spin_lock_irq(&list_lock);
 	list_add(&mdev->list, &video_devices);
 	spin_unlock_irq(&list_lock);
-	v4l2_info(&mdev->v4l2_dev, "aim_probe_channel() done\n");
+	v4l2_info(&mdev->v4l2_dev, "comp_probe_channel() done\n");
 	return 0;
 
 err_unreg:
@@ -547,48 +546,48 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
 	return ret;
 }
 
-static int aim_disconnect_channel(struct most_interface *iface,
-				  int channel_idx)
+static int comp_disconnect_channel(struct most_interface *iface,
+				   int channel_idx)
 {
-	struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
+	struct most_video_dev *mdev = get_comp_dev(iface, channel_idx);
 
 	if (!mdev) {
 		pr_err("no such channel is linked\n");
 		return -ENOENT;
 	}
 
-	v4l2_info(&mdev->v4l2_dev, "aim_disconnect_channel()\n");
+	v4l2_info(&mdev->v4l2_dev, "comp_disconnect_channel()\n");
 
 	spin_lock_irq(&list_lock);
 	list_del(&mdev->list);
 	spin_unlock_irq(&list_lock);
 
-	aim_unregister_videodev(mdev);
+	comp_unregister_videodev(mdev);
 	v4l2_device_disconnect(&mdev->v4l2_dev);
 	v4l2_device_put(&mdev->v4l2_dev);
 	return 0;
 }
 
-static struct most_aim aim_info = {
-	.name = "aim_v4l",
-	.probe_channel = aim_probe_channel,
-	.disconnect_channel = aim_disconnect_channel,
-	.rx_completion = aim_rx_data,
+static struct core_component comp_info = {
+	.name = "video",
+	.probe_channel = comp_probe_channel,
+	.disconnect_channel = comp_disconnect_channel,
+	.rx_completion = comp_rx_data,
 };
 
-static int __init aim_init(void)
+static int __init comp_init(void)
 {
 	spin_lock_init(&list_lock);
-	return most_register_aim(&aim_info);
+	return most_register_component(&comp_info);
 }
 
-static void __exit aim_exit(void)
+static void __exit comp_exit(void)
 {
 	struct most_video_dev *mdev, *tmp;
 
 	/*
 	 * As the mostcore currently doesn't call disconnect_channel()
-	 * for linked channels while we call most_deregister_aim()
+	 * for linked channels while we call most_deregister_component()
 	 * we simulate this call here.
 	 * This must be fixed in core.
 	 */
@@ -597,20 +596,20 @@ static void __exit aim_exit(void)
 		list_del(&mdev->list);
 		spin_unlock_irq(&list_lock);
 
-		aim_unregister_videodev(mdev);
+		comp_unregister_videodev(mdev);
 		v4l2_device_disconnect(&mdev->v4l2_dev);
 		v4l2_device_put(&mdev->v4l2_dev);
 		spin_lock_irq(&list_lock);
 	}
 	spin_unlock_irq(&list_lock);
 
-	most_deregister_aim(&aim_info);
+	most_deregister_component(&comp_info);
 	BUG_ON(!list_empty(&video_devices));
 }
 
-module_init(aim_init);
-module_exit(aim_exit);
+module_init(comp_init);
+module_exit(comp_exit);
 
-MODULE_DESCRIPTION("V4L2 Application Interface Module for MostCore");
+MODULE_DESCRIPTION("V4L2 Component for MostCore");
 MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
 MODULE_LICENSE("GPL");
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 18/26] staging: most: core: fix comment sections
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (15 preceding siblings ...)
  2017-10-13 14:33 ` [PATCH v2 17/26] staging: most: change designator for modules interfacing userspace Christian Gromm
@ 2017-10-13 14:33 ` Christian Gromm
  2017-10-13 14:33 ` [PATCH v2 19/26] staging: most: core: fix formatting Christian Gromm
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:33 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch updates and corrects the comment sections of the code.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 87 +++++++++++++++++++--------------------------
 drivers/staging/most/core.h | 40 ++++++++++-----------
 2 files changed, 55 insertions(+), 72 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 7961690..e3736bb 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -116,15 +116,9 @@ int most_match(struct device *dev, struct device_driver *drv)
 	_mbo;								\
 })
 
-/*		     ___	     ___
- *		     ___C H A N N E L___
- */
-
-
 /**
  * most_free_mbo_coherent - free an MBO and its coherent buffer
- * @mbo: buffer to be released
- *
+ * @mbo: most buffer
  */
 static void most_free_mbo_coherent(struct mbo *mbo)
 {
@@ -486,9 +480,6 @@ static ssize_t set_packets_per_xact_store(struct device *dev,
 	NULL,
 };
 
-/*		     ___	       ___
- *		     ___I N S T A N C E___
- */
 static ssize_t description_show(struct device *dev,
 				struct device_attribute *attr,
 				char *buf)
@@ -602,26 +593,26 @@ static ssize_t components_show(struct device_driver *drv, char *buf)
 	return offs;
 }
 /**
- * split_string - parses and changes string in the buffer buf and
- * splits it into two mandatory and one optional substrings.
+ * split_string - parses buf and extracts ':' separated substrings.
  *
  * @buf: complete string from attribute 'add_channel'
- * @a: address of pointer to 1st substring (=instance name)
- * @b: address of pointer to 2nd substring (=channel name)
- * @c: optional address of pointer to 3rd substring (=user defined name)
+ * @a: storage for 1st substring (=interface name)
+ * @b: storage for 2nd substring (=channel name)
+ * @c: storage for 3rd substring (=component name)
+ * @d: storage optional 4th substring (=user defined name)
  *
  * Examples:
  *
- * Input: "mdev0:ch6:my_channel\n" or
- *        "mdev0:ch6:my_channel"
+ * Input: "mdev0:ch6:cdev:my_channel\n" or
+ *        "mdev0:ch6:cdev:my_channel"
  *
- * Output: *a -> "mdev0", *b -> "ch6", *c -> "my_channel"
+ * Output: *a -> "mdev0", *b -> "ch6", *c -> "cdev" *d -> "my_channel"
  *
- * Input: "mdev1:ep81\n"
- * Output: *a -> "mdev1", *b -> "ep81", *c -> ""
+ * Input: "mdev1:ep81:cdev\n"
+ * Output: *a -> "mdev1", *b -> "ep81", *c -> "cdev" *d -> ""
  *
  * Input: "mdev1:ep81"
- * Output: *a -> "mdev1", *b -> "ep81", *c == NULL
+ * Output: *a -> "mdev1", *b -> "ep81", *c -> "cdev" *d == NULL
  */
 static int split_string(char *buf, char **a, char **b, char **c, char **d)
 {
@@ -651,11 +642,9 @@ static int match_bus_dev(struct device *dev, void *data)
 }
 
 /**
- * get_channel - get pointer to channel object
- * @mdev: name of the device instance
- * @mdev_ch: name of the respective channel
- *
- * This retrieves the pointer to a channel object.
+ * get_channel - get pointer to channel
+ * @mdev: name of the device interface
+ * @mdev_ch: name of channel
  */
 static struct most_channel *get_channel(char *mdev, char *mdev_ch)
 {
@@ -699,23 +688,22 @@ static int link_channel_to_component(struct most_channel *c,
 }
 
 /**
- * add_link_store - store() function for add_link attribute
- * @comp_obj: pointer to component object
- * @attr: its attributes
+ * add_link_store - store function for add_link attribute
+ * @drv: device driver
  * @buf: buffer
  * @len: buffer length
  *
  * This parses the string given by buf and splits it into
- * three substrings. Note: third substring is optional. In case a cdev
- * component is loaded the optional 3rd substring will make up the name of
+ * four substrings. Note: last substring is optional. In case a cdev
+ * component is loaded the optional 4th substring will make up the name of
  * device node in the /dev directory. If omitted, the device node will
  * inherit the channel's name within sysfs.
  *
- * Searches for a pair of device and channel and probes the component
+ * Searches for (device, channel) pair and probes the component
  *
  * Example:
- * (1) echo "mdev0:ch6:my_rxchannel" >add_link
- * (2) echo "mdev1:ep81" >add_link
+ * (1) echo "mdev0:ch6:cdev:my_rxchannel" >add_link
+ * (2) echo "mdev1:ep81:cdev" >add_link
  *
  * (1) would create the device node /dev/my_rxchannel
  * (2) would create the device node /dev/mdev1-ep81
@@ -761,8 +749,7 @@ static ssize_t add_link_store(struct device_driver *drv,
 
 /**
  * remove_link_store - store function for remove_link attribute
- * @comp_obj: pointer to component object
- * @attr: its attributes
+ * @drv: device driver
  * @buf: buffer
  * @len: buffer length
  *
@@ -823,9 +810,6 @@ static ssize_t remove_link_store(struct device_driver *drv,
 	&mc_attr_group,
 	NULL,
 };
-/*		     ___       ___
- *		     ___C O R E___
- */
 
 static inline void trash_mbo(struct mbo *mbo)
 {
@@ -917,7 +901,7 @@ static int run_enqueue_thread(struct most_channel *c, int channel_id)
 
 /**
  * arm_mbo - recycle MBO for further usage
- * @mbo: buffer object
+ * @mbo: most buffer
  *
  * This puts an MBO back to the list to have it ready for up coming
  * tx transactions.
@@ -1011,7 +995,7 @@ static int arm_mbo_chain(struct most_channel *c, int dir,
 
 /**
  * most_submit_mbo - submits an MBO to fifo
- * @mbo: pointer to the MBO
+ * @mbo: most buffer
  */
 void most_submit_mbo(struct mbo *mbo)
 {
@@ -1025,7 +1009,7 @@ void most_submit_mbo(struct mbo *mbo)
 
 /**
  * most_write_completion - write completion handler
- * @mbo: pointer to MBO
+ * @mbo: most buffer
  *
  * This recycles the MBO for further usage. In case the channel has been
  * poisoned, the MBO is scheduled to be trashed.
@@ -1071,6 +1055,7 @@ int channel_has_mbo(struct most_interface *iface, int id,
  * most_get_mbo - get pointer to an MBO of pool
  * @iface: pointer to interface instance
  * @id: channel ID
+ * @comp: driver component
  *
  * This attempts to get a free buffer out of the channel fifo.
  * Returns a pointer to MBO on success or NULL otherwise.
@@ -1116,7 +1101,7 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id,
 
 /**
  * most_put_mbo - return buffer to pool
- * @mbo: buffer object
+ * @mbo: most buffer
  */
 void most_put_mbo(struct mbo *mbo)
 {
@@ -1133,7 +1118,7 @@ void most_put_mbo(struct mbo *mbo)
 
 /**
  * most_read_completion - read completion handler
- * @mbo: pointer to MBO
+ * @mbo: most buffer
  *
  * This function is called by the HDM when data has been received from the
  * hardware and copied to the buffer of the MBO.
@@ -1174,6 +1159,7 @@ static void most_read_completion(struct mbo *mbo)
  * most_start_channel - prepares a channel for communication
  * @iface: pointer to interface instance
  * @id: channel ID
+ * @comp: driver component
  *
  * This prepares the channel for usage. Cross-checks whether the
  * channel's been properly configured.
@@ -1249,6 +1235,7 @@ int most_start_channel(struct most_interface *iface, int id,
  * most_stop_channel - stops a running channel
  * @iface: pointer to interface instance
  * @id: channel ID
+ * @comp: driver component
  */
 int most_stop_channel(struct most_interface *iface, int id,
 		      struct core_component *comp)
@@ -1306,8 +1293,8 @@ int most_stop_channel(struct most_interface *iface, int id,
 EXPORT_SYMBOL_GPL(most_stop_channel);
 
 /**
- * most_register_component - registers an component (driver) with the core
- * @comp: instance of component to be registered
+ * most_register_component - registers a driver component with the core
+ * @comp: driver component
  */
 int most_register_component(struct core_component *comp)
 {
@@ -1340,8 +1327,8 @@ static int disconnect_channels(struct device *dev, void *data)
 }
 
 /**
- * most_deregister_component - deregisters an component (driver) with the core
- * @comp: component to be removed
+ * most_deregister_component - deregisters a driver component with the core
+ * @comp: driver component
  */
 int most_deregister_component(struct core_component *comp)
 {
@@ -1369,7 +1356,7 @@ static void release_channel(struct device *dev)
 
 /**
  * most_register_interface - registers an interface with core
- * @iface: pointer to the instance of the interface description.
+ * @iface: device interface
  *
  * Allocates and initializes a new interface instance and all of its channels.
  * Returns a pointer to kobject or an error pointer.
@@ -1477,7 +1464,7 @@ int most_register_interface(struct most_interface *iface)
 
 /**
  * most_deregister_interface - deregisters an interface with core
- * @iface: pointer to the interface instance description.
+ * @iface: device interface
  *
  * Before removing an interface instance from the list, all running
  * channels are stopped and poisoned.
diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h
index d74276d..d6e9b87 100644
--- a/drivers/staging/most/core.h
+++ b/drivers/staging/most/core.h
@@ -1,6 +1,5 @@
 /*
- * most.h - Interface between MostCore,
- *   Hardware Dependent Module (HDM) and Application Interface Module (AIM).
+ * most.h - API for component and adapter drivers
  *
  * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG
  *
@@ -12,13 +11,6 @@
  * This file is licensed under GPLv2.
  */
 
-/*
- * Authors:
- *   Andrey Shvetsov <andrey.shvetsov@k2l.de>
- *   Christian Gromm <christian.gromm@microchip.com>
- *   Sebastian Graf
- */
-
 #ifndef __MOST_CORE_H__
 #define __MOST_CORE_H__
 
@@ -80,22 +72,22 @@ enum mbo_status_flags {
  * The value is bitwise OR-combination of the values from the
  * enumeration most_channel_data_type. Zero is allowed value and means
  * "channel may not be used".
- * @num_buffer_packet: Maximum number of buffers supported by this channel
+ * @num_buffers_packet: Maximum number of buffers supported by this channel
  * for packet data types (Async,Control,QoS)
  * @buffer_size_packet: Maximum buffer size supported by this channel
  * for packet data types (Async,Control,QoS)
- * @num_buffer_streaming: Maximum number of buffers supported by this channel
+ * @num_buffers_streaming: Maximum number of buffers supported by this channel
  * for streaming data types (Sync,AV Packetized)
  * @buffer_size_streaming: Maximum buffer size supported by this channel
  * for streaming data types (Sync,AV Packetized)
  * @name_suffix: Optional suffix providean by an HDM that is attached to the
  * regular channel name.
  *
- * Describes the capabilities of a MostCore channel like supported Data Types
+ * Describes the capabilities of a MOST channel like supported Data Types
  * and directions. This information is provided by an HDM for the MostCore.
  *
  * The Core creates read only sysfs attribute files in
- * /sys/devices/virtual/most/mostcore/devices/mdev-#/mdev#-ch#/ with the
+ * /sys/devices/most/mdev#/<channel>/ with the
  * following attributes:
  *	-available_directions
  *	-available_datatypes
@@ -130,7 +122,7 @@ struct most_channel_capability {
  * @packets_per_xact: number of MOST frames that are packet inside one USB
  *		      packet. This is USB specific
  *
- * Describes the configuration for a MostCore channel. This information is
+ * Describes the configuration for a MOST channel. This information is
  * provided from the MostCore to a HDM (like the Medusa PCIe Interface) as a
  * parameter of the "configure" function call.
  */
@@ -154,6 +146,7 @@ struct most_channel_config {
  *
  * @list: list head for use by the mbo's current owner
  * @ifp: (in) associated interface instance
+ * @num_buffers_ptr: amount of pool buffers
  * @hdm_channel_id: (in) HDM channel instance
  * @virt_address: (in) kernel virtual address of the buffer
  * @bus_address: (in) bus address of the buffer
@@ -162,15 +155,15 @@ struct most_channel_config {
  * @status: (out) transfer status
  * @complete: (in) completion routine
  *
- * The MostCore allocates and initializes the MBO.
+ * The core allocates and initializes the MBO.
  *
- * The HDM receives MBO for transfer from MostCore with the call to enqueue().
+ * The HDM receives MBO for transfer from the core with the call to enqueue().
  * The HDM copies the data to- or from the buffer depending on configured
  * channel direction, set "processed_length" and "status" and completes
  * the transfer procedure by calling the completion routine.
  *
- * At the end the MostCore deallocates the MBO or recycles it for further
- * transfers for the same or different HDM.
+ * Finally, the MBO is being deallocated or recycled for further
+ * transfers of the same or a different HDM.
  *
  * Directions of usage:
  * The core driver should never access any MBO fields (even if marked
@@ -203,10 +196,12 @@ struct mbo {
 /**
  * Interface instance description.
  *
- * Describes one instance of an interface like Medusa PCIe or Vantage USB.
+ * Describes an interface of a MOST device the core driver is bound to.
  * This structure is allocated and initialized in the HDM. MostCore may not
  * modify this structure.
  *
+ * @dev: the actual device
+ * @mod: module
  * @interface Interface type. \sa most_interface_type.
  * @description PRELIMINARY.
  *   Unique description of the device instance from point of view of the
@@ -259,14 +254,15 @@ struct most_interface {
 };
 
 #define to_most_interface(d) container_of(d, struct most_interface, dev)
+
 /**
- * struct most_aim - identifies MOST device driver to mostcore
- * @name: Driver name
+ * struct core_component - identifies a loadable component for the mostcore
+ * @list: list_head
+ * @name: component name
  * @probe_channel: function for core to notify driver about channel connection
  * @disconnect_channel: callback function to disconnect a certain channel
  * @rx_completion: completion handler for received packets
  * @tx_completion: completion handler for transmitted packets
- * @context: context pointer to be used by mostcore
  */
 struct core_component {
 	struct list_head list;
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 19/26] staging: most: core: fix formatting
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (16 preceding siblings ...)
  2017-10-13 14:33 ` [PATCH v2 18/26] staging: most: core: fix comment sections Christian Gromm
@ 2017-10-13 14:33 ` Christian Gromm
  2017-10-13 14:33 ` [PATCH v2 20/26] staging: most: usb: clear functional stall on tx endpoint Christian Gromm
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:33 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch fixes coding style violations.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index e3736bb..7cbef80 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -290,7 +290,6 @@ static ssize_t set_number_of_buffers_store(struct device *dev,
 					   size_t count)
 {
 	struct most_channel *c = to_channel(dev);
-
 	int ret = kstrtou16(buf, 0, &c->cfg.num_buffers);
 
 	if (ret)
@@ -313,7 +312,6 @@ static ssize_t set_buffer_size_store(struct device *dev,
 				     size_t count)
 {
 	struct most_channel *c = to_channel(dev);
-
 	int ret = kstrtou16(buf, 0, &c->cfg.buffer_size);
 
 	if (ret)
@@ -407,7 +405,6 @@ static ssize_t set_subbuffer_size_store(struct device *dev,
 					size_t count)
 {
 	struct most_channel *c = to_channel(dev);
-
 	int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size);
 
 	if (ret)
@@ -430,7 +427,6 @@ static ssize_t set_packets_per_xact_store(struct device *dev,
 					  size_t count)
 {
 	struct most_channel *c = to_channel(dev);
-
 	int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact);
 
 	if (ret)
@@ -683,7 +679,6 @@ static int link_channel_to_component(struct most_channel *c,
 		*comp_ptr = NULL;
 		return ret;
 	}
-
 	return 0;
 }
 
@@ -724,9 +719,7 @@ static ssize_t add_link_store(struct device_driver *drv,
 	size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
 
 	strlcpy(buffer, buf, max_len);
-
-	ret = split_string(buffer, &mdev, &mdev_ch, &comp_name,
-			   &comp_param);
+	ret = split_string(buffer, &mdev, &mdev_ch, &comp_name, &comp_param);
 	if (ret)
 		return ret;
 	comp = match_component(comp_name);
@@ -743,7 +736,6 @@ static ssize_t add_link_store(struct device_driver *drv,
 	ret = link_channel_to_component(c, comp, comp_param);
 	if (ret)
 		return ret;
-
 	return len;
 }
 
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 20/26] staging: most: usb: clear functional stall on tx endpoint
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (17 preceding siblings ...)
  2017-10-13 14:33 ` [PATCH v2 19/26] staging: most: core: fix formatting Christian Gromm
@ 2017-10-13 14:33 ` Christian Gromm
  2017-10-13 14:33 ` [PATCH v2 21/26] staging: most: core: fix data type Christian Gromm
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:33 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch triggers the host to send a control request to
clear the endpoint's Halt feature.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/usb/usb.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c
index 0624ca9..7577351 100644
--- a/drivers/staging/most/usb/usb.c
+++ b/drivers/staging/most/usb/usb.c
@@ -815,6 +815,21 @@ static void wq_clear_halt(struct work_struct *wq_obj)
 	if (usb_clear_halt(mdev->usb_device, pipe))
 		dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n");
 
+	/* If the functional Stall condition has been set on an
+	 * asynchronous rx channel, we need to clear the tx channel
+	 * too, since the hardware runs its clean-up sequence on both
+	 * channels, as they are physically one on the network.
+	 *
+	 * The USB interface that exposes the asynchronous channels
+	 * contains always two endpoints, and two only.
+	 */
+	if (mdev->conf[channel].data_type == MOST_CH_ASYNC &&
+	    mdev->conf[channel].direction == MOST_CH_RX) {
+		int peer = 1 - channel;
+		int snd_pipe = usb_sndbulkpipe(mdev->usb_device,
+					       mdev->ep_address[peer]);
+		usb_clear_halt(mdev->usb_device, snd_pipe);
+	}
 	mdev->is_channel_healthy[channel] = true;
 	most_resume_enqueue(&mdev->iface, channel);
 	mutex_unlock(&mdev->io_mutex);
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 21/26] staging: most: core: fix data type
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (18 preceding siblings ...)
  2017-10-13 14:33 ` [PATCH v2 20/26] staging: most: usb: clear functional stall on tx endpoint Christian Gromm
@ 2017-10-13 14:33 ` Christian Gromm
  2017-10-13 14:33 ` [PATCH v2 22/26] staging: most: core: check value returned by match function Christian Gromm
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:33 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch fixes the type used to manage the channels of an
registered MOST interface.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h
index d6e9b87..7c44791 100644
--- a/drivers/staging/most/core.h
+++ b/drivers/staging/most/core.h
@@ -238,7 +238,7 @@ struct most_interface {
 	struct module *mod;
 	enum most_interface_type interface;
 	const char *description;
-	int num_channels;
+	unsigned int num_channels;
 	struct most_channel_capability *channel_vector;
 	int (*configure)(struct most_interface *iface, int channel_idx,
 			 struct most_channel_config *channel_config);
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 22/26] staging: most: core: check value returned by match function
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (19 preceding siblings ...)
  2017-10-13 14:33 ` [PATCH v2 21/26] staging: most: core: fix data type Christian Gromm
@ 2017-10-13 14:33 ` Christian Gromm
  2017-10-13 14:33 ` [PATCH v2 23/26] staging: most: update driver usage file Christian Gromm
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:33 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch adds a check for the pointer returned by the function
match_component. It is needed to prevent a NULL pointer dereference in
case the provided component name does not match any list entry.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 7cbef80..c061e67 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -723,6 +723,8 @@ static ssize_t add_link_store(struct device_driver *drv,
 	if (ret)
 		return ret;
 	comp = match_component(comp_name);
+	if (!comp)
+		return -ENODEV;
 	if (!comp_param || *comp_param == 0) {
 		snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev,
 			 mdev_ch);
@@ -766,6 +768,8 @@ static ssize_t remove_link_store(struct device_driver *drv,
 	if (ret)
 		return ret;
 	comp = match_component(comp_name);
+	if (!comp)
+		return -ENODEV;
 	c = get_channel(mdev, mdev_ch);
 	if (!c)
 		return -ENODEV;
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 23/26] staging: most: update driver usage file
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (20 preceding siblings ...)
  2017-10-13 14:33 ` [PATCH v2 22/26] staging: most: core: check value returned by match function Christian Gromm
@ 2017-10-13 14:33 ` Christian Gromm
  2017-10-13 14:33 ` [PATCH v2 24/26] staging: most: cdev: bundle module variables in structure Christian Gromm
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:33 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

This patch keeps the usage file up to date.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 .../staging/most/Documentation/driver_usage.txt    | 192 +++++++++++----------
 1 file changed, 105 insertions(+), 87 deletions(-)

diff --git a/drivers/staging/most/Documentation/driver_usage.txt b/drivers/staging/most/Documentation/driver_usage.txt
index a4dc0c3..bb9b4e8 100644
--- a/drivers/staging/most/Documentation/driver_usage.txt
+++ b/drivers/staging/most/Documentation/driver_usage.txt
@@ -23,20 +23,29 @@ audio/video streaming. Therefore, the driver perfectly fits to the mission
 of Automotive Grade Linux to create open source software solutions for
 automotive applications.
 
-The driver consists basically of three layers. The hardware layer, the
-core layer and the application layer. The core layer consists of the core
-module only. This module handles the communication flow through all three
-layers, the configuration of the driver, the configuration interface
-representation in sysfs, and the buffer management.
-For each of the other two layers a selection of modules is provided. These
-modules can arbitrarily be combined to meet the needs of the desired
-system architecture. A module of the hardware layer is referred to as an
-HDM (hardware dependent module). Each module of this layer handles exactly
-one of the peripheral interfaces of a network interface controller (e.g.
-USB, MediaLB, I2C). A module of the application layer is referred to as an
-AIM (application interfacing module). The modules of this layer give access
-to MOST via one the following ways: character devices, ALSA, Networking or
-V4L2.
+The MOST driver uses module stacking to divide the associated modules into
+three layers. From bottom up these layers are: the adapter layer, the core
+layer and the application layer. The core layer implements the MOST
+subsystem and consists basically of the module core.c and its API. It
+registers the MOST bus with the kernel's device model, handles the data
+routing through all three layers, the configuration of the driver, the
+representation of the configuration interface in sysfs and the buffer
+management.
+
+For each of the other two layers a set of modules is provided. Those can be
+arbitrarily combined with the core to meet the connectivity of the desired
+system architecture.
+
+A module of the adapter layer is basically a device driver for a different
+subsystem. It is registered with the core to connect the MOST subsystem to
+the attached network interface controller hardware. Hence, a given module
+of this layer is designed to handle exactly one of the peripheral
+interfaces (e.g. USB, MediaLB, I2C) the hardware provides.
+
+A module of the application layer is referred to as a core comoponent,
+which kind of extends the core by providing connectivity to the user space.
+Applications, then, can access a MOST network via character devices, an
+ALSA soundcard, a Network adapter or a V4L2 capture device.
 
 To physically access MOST, an Intelligent Network Interface Controller
 (INIC) is needed. For more information on available controllers visit:
@@ -44,15 +53,14 @@ www.microchip.com
 
 
 
-		Section 1.1 Hardware Layer
+		Section 1.1 Adapter Layer
 
-The hardware layer contains so called hardware dependent modules (HDM). For each
-peripheral interface the hardware supports the driver has a suitable module
-that handles the interface.
-
-The HDMs encapsulate the peripheral interface specific knowledge of the driver
-and provides an easy way of extending the number of supported interfaces.
-Currently the following HDMs are available:
+The adapter layer contains a pool of device drivers. For each peripheral
+interface the hardware supports there is one suitable module that handles
+the interface. Adapter drivers encapsulate the peripheral interface
+specific knowledge of the MOST driver stack and provide an easy way of
+extending the number of supported interfaces. Currently the following
+interfaces are available:
 
 	1) MediaLB (DIM2)
 	   Host wants to communicate with hardware via MediaLB.
@@ -63,26 +71,34 @@ Currently the following HDMs are available:
 	3) USB
 	   Host wants to communicate with the hardware via USB.
 
+Once an adapter driver recognizes a MOST device being attached, it
+registers it with the core, which, in turn, assigns the necessary members
+of the embedded struct device (e.g. the bus this device belongs to and
+attribute groups) and registers it with the kernel's device model.
 
-		Section 1.2 Core Layer
-
-The core layer contains the mostcore module only, which processes the driver
-configuration via sysfs, buffer management and data forwarding.
 
+		Section 1.2 Core Layer
 
+This layer implements the MOST subsystem. It contains the core module and
+the header file most.h that exposes the API of the core. When inserted in
+the kernel, it registers the MOST bus_type with the kernel's device model
+and registers itself as a device driver for this bus. Besides these meta
+tasks the core populates the configuration directory for a registered MOST
+device (represented by struct most_interface) in sysfs and processes the
+configuration of the device's interface. The core layer also handles the
+buffer management and the data/message routing.
 
-		Section 1.2 Application Layer
 
-The application layer contains so called application interfacing modules (AIM).
-Depending on how the driver should interface to the application, one or more
-suitable modules can be selected.
+		Section 1.3 Application Layer
 
-The AIMs encapsulate the application interface specific knowledge of the driver
-and provides access to user space or other kernel subsystems.
-Currently the following AIMs are available
+This layer contains a pool of device drivers that are components of the
+core designed to make up the userspace experience of the MOST driver stack.
+Depending on how an application is meant to interface the driver, one or
+more modules of this pool can be registered with the core. Currently the
+following components are available
 
 	1) Character Device
-	   Applications can access the driver by means of character devices.
+	   Userspace can access the driver by means of character devices.
 
 	2) Networking
 	   Standard networking applications (e.g. iperf) can by used to access
@@ -97,84 +113,86 @@ Currently the following AIMs are available
 	   used to access the driver via the ALSA subsystem.
 
 
+		Section 2 Usage of the MOST Driver
 
-		Section 2 Configuration
+		Section 2.1 Configuration
 
-See ABI/sysfs-class-most.txt
+See ABI/sysfs-bus-most.txt
 
 
+		Section 2.2 Routing Channels
 
-		Section 3 USB Padding
+To connect a configured channel to a certain core component and make it
+accessible for user space applications, the driver attribute 'add_link' is
+used. The configuration string passed to it has the following format:
 
-When transceiving synchronous or isochronous data, the number of packets per USB
-transaction and the sub-buffer size need to be configured. These values
-are needed for the driver to process buffer padding, as expected by hardware,
-which is for performance optimization purposes of the USB transmission.
+	"device_name:channel_name:component_name:link_name[.param]"
 
-When transmitting synchronous data the allocated channel width needs to be
-written to 'set_subbuffer_size'. Additionally, the number of MOST frames that
-should travel to the host within one USB transaction need to be written to
-'packets_per_xact'.
+It is the concatenation of up to four substrings separated by a colon. The
+substrings contain the names of the MOST interface, the channel, the
+component driver and a custom name with which the link is going to be
+referenced with. Since some components need additional information, the
+link name can be extended with a component-specific parameter (separated by
+a dot). In case the character device component is loaded, the handle would
+also appear as a device node in the /dev directory.
 
-Internally the synchronous threshold is calculated as follows:
+Cdev component example:
+        $ echo "mdev0:ep_81:cdev:my_rx_channel" >$(DRV_DIR)/add_link
 
-	frame_size = set_subbuffer_size * packets_per_xact
 
-In case 'packets_per_xact' is set to 0xFF the maximum number of packets,
-allocated within one MOST frame, is calculated that fit into _one_ 512 byte
-USB full packet.
+Sound component example:
 
-	frame_size = floor(MTU_USB / bandwidth_sync) * bandwidth_sync
+The sound component needs an additional parameter to determine the audio
+resolution that is going to be used. The following formats are available:
 
-This frame_size is the number of synchronous data within an USB transaction,
-which renders MTU_USB - frame_size bytes for padding.
+	- "1x8" (Mono)
+	- "2x16" (16-bit stereo)
+	- "2x24" (24-bit stereo)
+	- "2x32" (32-bit stereo)
+	- "6x16" (16-bit surround 5.1)
 
-When transmitting isochronous AVP data the desired packet size needs to be
-written to 'set_subbuffer_size' and hardware will always expect two isochronous
-packets within one USB transaction. This renders
+        $ echo "mdev0:ep_81:sound:most51_playback.6x16" >$(DRV_DIR)/add_link
 
-	MTU_USB - (2 * set_subbuffer_size)
 
-bytes for padding.
-
-Note that at least 2 times set_subbuffer_size bytes for isochronous data or
-set_subbuffer_size times packts_per_xact bytes for synchronous data need to be
-put in the transmission buffer and passed to the driver.
 
-Since HDMs are allowed to change a chosen configuration to best fit its
-constraints, it is recommended to always double check the configuration and read
-back the previously written files.
+		Section 2.3 USB Padding
 
+When transceiving synchronous or isochronous data, the number of packets
+per USB transaction and the sub-buffer size need to be configured. These
+values are needed for the driver to process buffer padding, as expected by
+hardware, which is for performance optimization purposes of the USB
+transmission.
 
+When transmitting synchronous data the allocated channel width needs to be
+written to 'set_subbuffer_size'. Additionally, the number of MOST frames
+that should travel to the host within one USB transaction need to be
+written to 'packets_per_xact'.
 
-		Section 4 Routing Channels
+The driver, then, calculates the synchronous threshold as follows:
 
-To connect a channel that has been configured as outlined above to an AIM and
-make it accessible to user space applications, the attribute file 'add_link' is
-used. To actually bind a channel to the AIM a string needs to be written to the
-file that complies with the following syntax:
+	frame_size = set_subbuffer_size * packets_per_xact
 
-	"most_device:channel_name:link_name[.param]"
+In case 'packets_per_xact' is set to 0xFF the maximum number of packets,
+allocated within one MOST frame, is calculated that fit into _one_ 512 byte
+USB full packet.
 
-The example above links the channel "channel_name" of the device "most_device"
-to the AIM. In case the AIM interfaces the VFS this would also create a device
-node "link_name" in the /dev directory. The parameter "param" is an AIM dependent
-string, which can be omitted in case the used AIM does not make any use of it.
+	frame_size = floor(MTU_USB / bandwidth_sync) * bandwidth_sync
 
-Cdev AIM example:
-        $ echo "mdev0:ep_81:my_rx_channel" >add_link
-        $ echo "mdev0:ep_81" >add_link
+This frame_size is the number of synchronous data within an USB
+transaction, which renders MTU_USB - frame_size bytes for padding.
 
+When transmitting isochronous AVP data the desired packet size needs to be
+written to 'set_subbuffer_size' and hardware will always expect two
+isochronous packets within one USB transaction. This renders
 
-Sound/ALSA AIM example:
+	MTU_USB - (2 * set_subbuffer_size)
 
-The sound/ALSA AIM needs an additional parameter to determine the audio resolution
-that is going to be used. The following strings can be used:
+bytes for padding.
 
-	- "1x8" (Mono)
-	- "2x16" (16-bit stereo)
-	- "2x24" (24-bit stereo)
-	- "2x32" (32-bit stereo)
+Note that at least (2 * set_subbuffer_size) bytes for isochronous data or
+(set_subbuffer_size * packts_per_xact) bytes for synchronous data need to
+be put in the transmission buffer and passed to the driver.
 
-        $ echo "mdev0:ep_81:audio_rx.2x16" >add_link
-        $ echo "mdev0:ep_81" >add_link
+Since adapter drivers are allowed to change a chosen configuration to best
+fit its constraints, it is recommended to always double check the
+configuration and read back the previously written files.
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 24/26] staging: most: cdev: bundle module variables in structure
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (21 preceding siblings ...)
  2017-10-13 14:33 ` [PATCH v2 23/26] staging: most: update driver usage file Christian Gromm
@ 2017-10-13 14:33 ` Christian Gromm
  2017-10-13 14:33 ` [PATCH v2 25/26] staging: most: core: remove class generation Christian Gromm
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:33 UTC (permalink / raw)
  To: gregkh; +Cc: driverdev-devel, Christian Gromm

This patch creates the structure comp to bundle the module variables.
For an improved readability some variables are renamed.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/cdev/cdev.c | 88 ++++++++++++++++++++--------------------
 1 file changed, 43 insertions(+), 45 deletions(-)

diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c
index 373baf2..c6d467b 100644
--- a/drivers/staging/most/cdev/cdev.c
+++ b/drivers/staging/most/cdev/cdev.c
@@ -24,11 +24,13 @@
 #include <linux/idr.h>
 #include <most/core.h>
 
-static dev_t comp_devno;
-static struct class *comp_class;
-static struct ida minor_id;
-static unsigned int major;
-static struct core_component cdev_comp;
+static struct cdev_component {
+	dev_t devno;
+	struct ida minor_id;
+	unsigned int major;
+	struct class *class;
+	struct core_component cc;
+} comp;
 
 struct comp_channel {
 	wait_queue_head_t wq;
@@ -52,13 +54,13 @@ struct comp_channel {
 
 static inline bool ch_has_mbo(struct comp_channel *c)
 {
-	return channel_has_mbo(c->iface, c->channel_id, &cdev_comp) > 0;
+	return channel_has_mbo(c->iface, c->channel_id, &comp.cc) > 0;
 }
 
 static inline bool ch_get_mbo(struct comp_channel *c, struct mbo **mbo)
 {
 	if (!kfifo_peek(&c->fifo, mbo)) {
-		*mbo = most_get_mbo(c->iface, c->channel_id, &cdev_comp);
+		*mbo = most_get_mbo(c->iface, c->channel_id, &comp.cc);
 		if (*mbo)
 			kfifo_in(&c->fifo, mbo, 1);
 	}
@@ -90,14 +92,14 @@ static void stop_channel(struct comp_channel *c)
 
 	while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1))
 		most_put_mbo(mbo);
-	most_stop_channel(c->iface, c->channel_id, &cdev_comp);
+	most_stop_channel(c->iface, c->channel_id, &comp.cc);
 }
 
 static void destroy_cdev(struct comp_channel *c)
 {
 	unsigned long flags;
 
-	device_destroy(comp_class, c->devno);
+	device_destroy(comp.class, c->devno);
 	cdev_del(&c->cdev);
 	spin_lock_irqsave(&ch_list_lock, flags);
 	list_del(&c->list);
@@ -106,7 +108,7 @@ static void destroy_cdev(struct comp_channel *c)
 
 static void destroy_channel(struct comp_channel *c)
 {
-	ida_simple_remove(&minor_id, MINOR(c->devno));
+	ida_simple_remove(&comp.minor_id, MINOR(c->devno));
 	kfifo_free(&c->fifo);
 	kfree(c);
 }
@@ -149,7 +151,7 @@ static int comp_open(struct inode *inode, struct file *filp)
 	}
 
 	c->mbo_offs = 0;
-	ret = most_start_channel(c->iface, c->channel_id, &cdev_comp);
+	ret = most_start_channel(c->iface, c->channel_id, &comp.cc);
 	if (!ret)
 		c->access_ref = 1;
 	mutex_unlock(&c->io_mutex);
@@ -441,7 +443,7 @@ static int comp_probe(struct most_interface *iface, int channel_id,
 	if (c)
 		return -EEXIST;
 
-	current_minor = ida_simple_get(&minor_id, 0, 0, GFP_KERNEL);
+	current_minor = ida_simple_get(&comp.minor_id, 0, 0, GFP_KERNEL);
 	if (current_minor < 0)
 		return current_minor;
 
@@ -451,7 +453,7 @@ static int comp_probe(struct most_interface *iface, int channel_id,
 		goto error_alloc_channel;
 	}
 
-	c->devno = MKDEV(major, current_minor);
+	c->devno = MKDEV(comp.major, current_minor);
 	cdev_init(&c->cdev, &channel_fops);
 	c->cdev.owner = THIS_MODULE;
 	cdev_add(&c->cdev, c->devno, 1);
@@ -471,11 +473,7 @@ static int comp_probe(struct most_interface *iface, int channel_id,
 	spin_lock_irqsave(&ch_list_lock, cl_flags);
 	list_add_tail(&c->list, &channel_list);
 	spin_unlock_irqrestore(&ch_list_lock, cl_flags);
-	c->dev = device_create(comp_class,
-				     NULL,
-				     c->devno,
-				     NULL,
-				     "%s", name);
+	c->dev = device_create(comp.class, NULL, c->devno, NULL, "%s", name);
 
 	if (IS_ERR(c->dev)) {
 		retval = PTR_ERR(c->dev);
@@ -492,16 +490,18 @@ static int comp_probe(struct most_interface *iface, int channel_id,
 	cdev_del(&c->cdev);
 	kfree(c);
 error_alloc_channel:
-	ida_simple_remove(&minor_id, current_minor);
+	ida_simple_remove(&comp.minor_id, current_minor);
 	return retval;
 }
 
-static struct core_component cdev_comp = {
-	.name = "cdev",
-	.probe_channel = comp_probe,
-	.disconnect_channel = comp_disconnect_channel,
-	.rx_completion = comp_rx_completion,
-	.tx_completion = comp_tx_completion,
+static struct cdev_component comp = {
+	.cc = {
+		.name = "cdev",
+		.probe_channel = comp_probe,
+		.disconnect_channel = comp_disconnect_channel,
+		.rx_completion = comp_rx_completion,
+		.tx_completion = comp_tx_completion,
+	},
 };
 
 static int __init mod_init(void)
@@ -510,32 +510,30 @@ static int __init mod_init(void)
 
 	pr_info("init()\n");
 
+	comp.class = class_create(THIS_MODULE, "most_cdev");
+	if (IS_ERR(comp.class)) {
+		pr_info("No udev support.\n");
+		return PTR_ERR(comp.class);
+	}
+
 	INIT_LIST_HEAD(&channel_list);
 	spin_lock_init(&ch_list_lock);
-	ida_init(&minor_id);
+	ida_init(&comp.minor_id);
 
-	err = alloc_chrdev_region(&comp_devno, 0, 50, "cdev");
+	err = alloc_chrdev_region(&comp.devno, 0, 50, "cdev");
 	if (err < 0)
 		goto dest_ida;
-	major = MAJOR(comp_devno);
-
-	comp_class = class_create(THIS_MODULE, "most_cdev_comp");
-	if (IS_ERR(comp_class)) {
-		pr_err("no udev support\n");
-		err = PTR_ERR(comp_class);
-		goto free_cdev;
-	}
-	err = most_register_component(&cdev_comp);
+	comp.major = MAJOR(comp.devno);
+	err = most_register_component(&comp.cc);
 	if (err)
-		goto dest_class;
+		goto free_cdev;
 	return 0;
 
-dest_class:
-	class_destroy(comp_class);
 free_cdev:
-	unregister_chrdev_region(comp_devno, 1);
+	unregister_chrdev_region(comp.devno, 1);
 dest_ida:
-	ida_destroy(&minor_id);
+	ida_destroy(&comp.minor_id);
+	class_destroy(comp.class);
 	return err;
 }
 
@@ -545,15 +543,15 @@ static void __exit mod_exit(void)
 
 	pr_info("exit module\n");
 
-	most_deregister_component(&cdev_comp);
+	most_deregister_component(&comp.cc);
 
 	list_for_each_entry_safe(c, tmp, &channel_list, list) {
 		destroy_cdev(c);
 		destroy_channel(c);
 	}
-	class_destroy(comp_class);
-	unregister_chrdev_region(comp_devno, 1);
-	ida_destroy(&minor_id);
+	unregister_chrdev_region(comp.devno, 1);
+	ida_destroy(&comp.minor_id);
+	class_destroy(comp.class);
 }
 
 module_init(mod_init);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 25/26] staging: most: core: remove class generation
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (22 preceding siblings ...)
  2017-10-13 14:33 ` [PATCH v2 24/26] staging: most: cdev: bundle module variables in structure Christian Gromm
@ 2017-10-13 14:33 ` Christian Gromm
  2017-10-13 14:33 ` [PATCH v2 26/26] staging: most: core: fix list traversing Christian Gromm
  2017-10-13 15:09 ` [PATCH v2 01/26] staging: most: rearrange source files Greg KH
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:33 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

This patch stops the core from generating a module owned class
and registering it with the kernel.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index c061e67..6ec56930 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -39,7 +39,6 @@
 	struct device dev;
 	struct device_driver drv;
 	struct bus_type bus;
-	struct class *class;
 	struct list_head comp_list;
 } mc;
 
@@ -1562,17 +1561,10 @@ static int __init most_init(void)
 		pr_info("Cannot register most bus\n");
 		return err;
 	}
-	mc.class = class_create(THIS_MODULE, "most");
-	if (IS_ERR(mc.class)) {
-		pr_info("No udev support.\n");
-		err = PTR_ERR(mc.class);
-		goto exit_bus;
-	}
-
 	err = driver_register(&mc.drv);
 	if (err) {
 		pr_info("Cannot register core driver\n");
-		goto exit_class;
+		goto exit_bus;
 	}
 	mc.dev.init_name = "most";
 	mc.dev.release = release_most_sub;
@@ -1584,8 +1576,6 @@ static int __init most_init(void)
 
 exit_driver:
 	driver_unregister(&mc.drv);
-exit_class:
-	class_destroy(mc.class);
 exit_bus:
 	bus_unregister(&mc.bus);
 	return err;
@@ -1596,7 +1586,6 @@ static void __exit most_exit(void)
 	pr_info("exit core module\n");
 	device_unregister(&mc.dev);
 	driver_unregister(&mc.drv);
-	class_destroy(mc.class);
 	bus_unregister(&mc.bus);
 	ida_destroy(&mdev_id);
 }
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 26/26] staging: most: core: fix list traversing
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (23 preceding siblings ...)
  2017-10-13 14:33 ` [PATCH v2 25/26] staging: most: core: remove class generation Christian Gromm
@ 2017-10-13 14:33 ` Christian Gromm
  2017-10-13 15:09 ` [PATCH v2 01/26] staging: most: rearrange source files Greg KH
  25 siblings, 0 replies; 27+ messages in thread
From: Christian Gromm @ 2017-10-13 14:33 UTC (permalink / raw)
  To: gregkh; +Cc: driverdev-devel, Andrey Shvetsov, Christian Gromm

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

This patch fixes the offset and data handling when traversing
the list of devices that are attached to the bus.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
v2: fix patch numeration

 drivers/staging/most/core.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c
index 6ec56930..7d94b47 100644
--- a/drivers/staging/most/core.c
+++ b/drivers/staging/most/core.c
@@ -542,10 +542,16 @@ static struct core_component *match_component(char *name)
 	return NULL;
 }
 
+struct show_links_data {
+	int offs;
+	char *buf;
+};
+
 int print_links(struct device *dev, void *data)
 {
-	int offs = 0;
-	char *buf = data;
+	struct show_links_data *d = data;
+	int offs = d->offs;
+	char *buf = d->buf;
 	struct most_channel *c;
 	struct most_interface *iface = to_most_interface(dev);
 
@@ -567,13 +573,16 @@ int print_links(struct device *dev, void *data)
 					 dev_name(&c->dev));
 		}
 	}
+	d->offs = offs;
 	return 0;
 }
 
 static ssize_t links_show(struct device_driver *drv, char *buf)
 {
-	bus_for_each_dev(&mc.bus, NULL, buf, print_links);
-	return strlen(buf);
+	struct show_links_data d = { .buf = buf };
+
+	bus_for_each_dev(&mc.bus, NULL, &d, print_links);
+	return d.offs;
 }
 
 static ssize_t components_show(struct device_driver *drv, char *buf)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 01/26] staging: most: rearrange source files
  2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
                   ` (24 preceding siblings ...)
  2017-10-13 14:33 ` [PATCH v2 26/26] staging: most: core: fix list traversing Christian Gromm
@ 2017-10-13 15:09 ` Greg KH
  25 siblings, 0 replies; 27+ messages in thread
From: Greg KH @ 2017-10-13 15:09 UTC (permalink / raw)
  To: Christian Gromm; +Cc: driverdev-devel

On Fri, Oct 13, 2017 at 04:32:45PM +0200, Christian Gromm wrote:
> This patch renames and moves the source files of the driver. Additionally,
> it adapts the ABI, Makefiles and Kconfig files of the kernel's build
> system.
> 
> Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
> ---
> v2: fix patch numeration
> 

When moving files, create the patch with '-M' to show the movement, and
not just an remove/add type of a patch.  That way it is much easier to
review.

And no patch 00/26 to say what these are all doing?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2017-10-13 15:09 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-13 14:32 [PATCH v2 01/26] staging: most: rearrange source files Christian Gromm
2017-10-13 14:32 ` [PATCH v2 02/26] staging: most: integrate driver in kernel's device model Christian Gromm
2017-10-13 14:32 ` [PATCH v2 03/26] staging: most: core: rename structure Christian Gromm
2017-10-13 14:32 ` [PATCH v2 04/26] staging: most: core: rename struct most_c_aim_obj to pipe Christian Gromm
2017-10-13 14:32 ` [PATCH v2 05/26] staging: most: core: rename struct memeber Christian Gromm
2017-10-13 14:32 ` [PATCH v2 06/26] staging: most: core: rename members aim* of struct most_channel Christian Gromm
2017-10-13 14:32 ` [PATCH v2 07/26] staging: most: core: use structure to pack driver specific data Christian Gromm
2017-10-13 14:32 ` [PATCH v2 08/26] staging: most: core: track aim modules with linked list Christian Gromm
2017-10-13 14:32 ` [PATCH v2 09/26] staging: most: core: let core manage aim attributes Christian Gromm
2017-10-13 14:32 ` [PATCH v2 10/26] staging: most: core: remove struct device from struct most_aim Christian Gromm
2017-10-13 14:32 ` [PATCH v2 11/26] staging: most: core: fix header file mostcore.h Christian Gromm
2017-10-13 14:32 ` [PATCH v2 12/26] staging: most: core: rename function Christian Gromm
2017-10-13 14:32 ` [PATCH v2 13/26] staging: most: core: replace struct most_inst_obj with struct interface_private Christian Gromm
2017-10-13 14:32 ` [PATCH v2 14/26] staging: most: core: make channel name accessible from struct most_channel Christian Gromm
2017-10-13 14:32 ` [PATCH v2 15/26] staging: most: core: remove context pointer from struct most_aim Christian Gromm
2017-10-13 14:33 ` [PATCH v2 16/26] staging: most: usb: remove pointer initialization Christian Gromm
2017-10-13 14:33 ` [PATCH v2 17/26] staging: most: change designator for modules interfacing userspace Christian Gromm
2017-10-13 14:33 ` [PATCH v2 18/26] staging: most: core: fix comment sections Christian Gromm
2017-10-13 14:33 ` [PATCH v2 19/26] staging: most: core: fix formatting Christian Gromm
2017-10-13 14:33 ` [PATCH v2 20/26] staging: most: usb: clear functional stall on tx endpoint Christian Gromm
2017-10-13 14:33 ` [PATCH v2 21/26] staging: most: core: fix data type Christian Gromm
2017-10-13 14:33 ` [PATCH v2 22/26] staging: most: core: check value returned by match function Christian Gromm
2017-10-13 14:33 ` [PATCH v2 23/26] staging: most: update driver usage file Christian Gromm
2017-10-13 14:33 ` [PATCH v2 24/26] staging: most: cdev: bundle module variables in structure Christian Gromm
2017-10-13 14:33 ` [PATCH v2 25/26] staging: most: core: remove class generation Christian Gromm
2017-10-13 14:33 ` [PATCH v2 26/26] staging: most: core: fix list traversing Christian Gromm
2017-10-13 15:09 ` [PATCH v2 01/26] staging: most: rearrange source files Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.