aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-kernel/most/files
diff options
context:
space:
mode:
authorChristian Gromm <christian.gromm@microchip.com>2017-11-09 14:38:17 +0100
committerChristian Gromm <christian.gromm@microchip.com>2017-11-09 14:38:30 +0100
commit3386278db196969e6b4c77b7d06e6d7dd1ed044c (patch)
tree14517b130efaf19d82ec201eb0403b640617babe /recipes-kernel/most/files
parent10c9f16b8853d0e4c2e75b4382122b6a6aa4a734 (diff)
recipes-kernel: most: update recipes
This patch updates the most.bb and most.bbappend files to be in sync with the recently pushed driver package to src/most. It adds and removes backport patches as needed new driver source tree. Change-Id: I091d925219eeb2986ce5b1545f41d3693500f7d3 Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
Diffstat (limited to 'recipes-kernel/most/files')
-rw-r--r--recipes-kernel/most/files/0001-aim-network-3.10.31-ltsi-backport.patch45
-rw-r--r--recipes-kernel/most/files/0001-aim-sound-3.10.31-ltsi-backport.patch29
-rw-r--r--recipes-kernel/most/files/0001-let-HDMs-do-the-coherent-memory-allocation.patch140
-rw-r--r--recipes-kernel/most/files/0001-src-most-net-add-skb_put_data-function.patch33
-rw-r--r--recipes-kernel/most/files/0002-most-pass-parent-devcie-to-snd_card_new.patch52
-rw-r--r--recipes-kernel/most/files/0002-src-most-add-auto-conf-feature.patch472
6 files changed, 505 insertions, 266 deletions
diff --git a/recipes-kernel/most/files/0001-aim-network-3.10.31-ltsi-backport.patch b/recipes-kernel/most/files/0001-aim-network-3.10.31-ltsi-backport.patch
deleted file mode 100644
index d0bbd72e8..000000000
--- a/recipes-kernel/most/files/0001-aim-network-3.10.31-ltsi-backport.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From 4c49b7ad9e3c1e64e4e6042e6fee357b5d9b3df2 Mon Sep 17 00:00:00 2001
-From: Christian Gromm <christian.gromm@microchip.com>
-Date: Mon, 23 Jan 2017 14:57:55 +0100
-Subject: [PATCH] aim-network: create backport patch for 3.10.31-ltsi
-
-Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
----
- aim-network/networking.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
-
-diff --git a/aim-network/networking.c b/aim-network/networking.c
-index ce1764c..e04b523 100644
---- a/aim-network/networking.c
-+++ b/aim-network/networking.c
-@@ -362,8 +362,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
-
- if (nd->tx.linked || nd->rx.linked) {
- struct net_device *dev =
-- alloc_netdev(0, "meth%d", NET_NAME_UNKNOWN,
-- most_nd_setup);
-+ alloc_netdev(0, "meth%d", most_nd_setup);
-
- if (!dev) {
- pr_err("no memory for net_device\n");
-@@ -483,7 +482,7 @@ static int aim_rx_data(struct mbo *mbo)
-
- if (nd->is_mamac) {
- /* dest */
-- ether_addr_copy(skb_put(skb, ETH_ALEN), dev->dev_addr);
-+ memcpy(skb_put(skb, ETH_ALEN), dev->dev_addr, ETH_ALEN);
-
- /* src */
- memcpy(skb_put(skb, 4), &zero, 4);
-@@ -577,7 +576,7 @@ void most_deliver_netinfo(struct most_interface *iface,
- 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);
-+ memcpy(dev->dev_addr, m, ETH_ALEN);
- complete(&nd->mac_compl);
- } else if (!ether_addr_equal(dev->dev_addr, m)) {
- netdev_warn(dev, "reject mac %02x-%02x-%02x-%02x-%02x-%02x\n",
---
-2.11.0
-
diff --git a/recipes-kernel/most/files/0001-aim-sound-3.10.31-ltsi-backport.patch b/recipes-kernel/most/files/0001-aim-sound-3.10.31-ltsi-backport.patch
deleted file mode 100644
index 31e9400df..000000000
--- a/recipes-kernel/most/files/0001-aim-sound-3.10.31-ltsi-backport.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 686130266ff7968edc863d398fba82bd0f78bf29 Mon Sep 17 00:00:00 2001
-From: Christian Gromm <christian.gromm@microchip.com>
-Date: Wed, 28 Sep 2016 13:43:36 +0200
-Subject: [PATCH 1/4] backport module
-
-This patch replaces function snd_card_new() with snd_card_create() to match
-AGL/Renesas kernel API.
-
-Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
----
- aim-sound/sound.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/aim-sound/sound.c b/aim-sound/sound.c
-index 3dc625c..af0af2d 100644
---- a/aim-sound/sound.c
-+++ b/aim-sound/sound.c
-@@ -595,7 +595,7 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id,
- return ret;
- }
-
-- ret = snd_card_new(NULL, -1, card_name, THIS_MODULE,
-+ ret = snd_card_create(-1, card_name, THIS_MODULE,
- sizeof(*channel), &card);
- if (ret < 0)
- return ret;
---
-1.7.9.5
-
diff --git a/recipes-kernel/most/files/0001-let-HDMs-do-the-coherent-memory-allocation.patch b/recipes-kernel/most/files/0001-let-HDMs-do-the-coherent-memory-allocation.patch
deleted file mode 100644
index b387faac1..000000000
--- a/recipes-kernel/most/files/0001-let-HDMs-do-the-coherent-memory-allocation.patch
+++ /dev/null
@@ -1,140 +0,0 @@
-From b4fe384dde3e230d8c252525fcd5297015b147d1 Mon Sep 17 00:00:00 2001
-From: Christian Gromm <christian.gromm@microchip.com>
-Date: Wed, 2 Aug 2017 14:51:20 +0200
-Subject: [PATCH 1/5] let HDMs do the coherent memory allocation
-
-On arm64/aarch64 architectures the allocation of coherent memory
-needs a device that has the dma_ops proberly set. That's why the
-core module of the MOST driver is no longer able to allocate this
-kind of memory. This patch moves the allocation process down to
-the HDM layer where the proper devices exist in either the USB
-host controller or the platform device.
-
-Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
-
-
-Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
----
- driver/hdm-dim2/dim2_hdm.c | 12 ++++++++++++
- driver/hdm-usb/hdm_usb.c | 18 ++++++++++++++++++
- driver/include/mostcore.h | 2 ++
- driver/mostcore/core.c | 17 +++++++++++------
- 4 files changed, 43 insertions(+), 6 deletions(-)
-
-diff --git a/hdm-dim2/dim2_hdm.c b/hdm-dim2/dim2_hdm.c
-index 35aee9f..1b164cf 100644
---- a/hdm-dim2/dim2_hdm.c
-+++ b/hdm-dim2/dim2_hdm.c
-@@ -722,6 +722,16 @@ static int poison_channel(struct most_interface *most_iface, int ch_idx)
- return ret;
- }
-
-+static void *dma_alloc(struct mbo *mbo, u32 size)
-+{
-+ return dma_alloc_coherent(NULL, size, &mbo->bus_address, GFP_KERNEL);
-+}
-+
-+static void dma_free(struct mbo *mbo, u32 size)
-+{
-+ dma_free_coherent(NULL, size, mbo->virt_address, mbo->bus_address);
-+}
-+
- /*
- * dim2_probe - dim2 probe handler
- * @pdev: platform device structure
-@@ -820,6 +830,8 @@ static int dim2_probe(struct platform_device *pdev)
- dev->most_iface.channel_vector = dev->capabilities;
- dev->most_iface.configure = configure_channel;
- dev->most_iface.enqueue = enqueue;
-+ dev->most_iface.dma_alloc = dma_alloc;
-+ dev->most_iface.dma_free = dma_free;
- dev->most_iface.poison_channel = poison_channel;
- dev->most_iface.request_netinfo = request_netinfo;
-
-diff --git a/hdm-usb/hdm_usb.c b/hdm-usb/hdm_usb.c
-index 3433646..0b689b5 100644
---- a/hdm-usb/hdm_usb.c
-+++ b/hdm-usb/hdm_usb.c
-@@ -629,6 +629,22 @@ _error:
- return retval;
- }
-
-+static void *hdm_dma_alloc(struct mbo *mbo, u32 size)
-+{
-+ struct most_dev *mdev = to_mdev(mbo->ifp);
-+
-+ return usb_alloc_coherent(mdev->usb_device, size, GFP_KERNEL,
-+ &mbo->bus_address);
-+}
-+
-+static void hdm_dma_free(struct mbo *mbo, u32 size)
-+{
-+ struct most_dev *mdev = to_mdev(mbo->ifp);
-+
-+ usb_free_coherent(mdev->usb_device, size, mbo->virt_address,
-+ mbo->bus_address);
-+}
-+
- /**
- * hdm_configure_channel - receive channel configuration from core
- * @iface: interface
-@@ -1140,6 +1156,8 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
- mdev->iface.request_netinfo = hdm_request_netinfo;
- mdev->iface.enqueue = hdm_enqueue;
- mdev->iface.poison_channel = hdm_poison_channel;
-+ mdev->iface.dma_alloc = hdm_dma_alloc;
-+ mdev->iface.dma_free = hdm_dma_free;
- mdev->iface.description = mdev->description;
- mdev->iface.num_channels = num_endpoints;
-
-diff --git a/include/mostcore.h b/include/mostcore.h
-index 5f8339b..deefe25 100644
---- a/include/mostcore.h
-+++ b/include/mostcore.h
-@@ -241,6 +241,8 @@ struct most_interface {
- const char *description;
- int num_channels;
- struct most_channel_capability *channel_vector;
-+ void *(*dma_alloc)(struct mbo *mbo, u32 size);
-+ void (*dma_free)(struct mbo *mbo, u32 size);
- int (*configure)(struct most_interface *iface, int channel_idx,
- struct most_channel_config *channel_config);
- int (*enqueue)(struct most_interface *iface, int channel_idx,
-diff --git a/mostcore/core.c b/mostcore/core.c
-index 4c580d1..931efb9 100644
---- a/mostcore/core.c
-+++ b/mostcore/core.c
-@@ -184,8 +184,10 @@ 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);
-+ if (c->iface->dma_free)
-+ c->iface->dma_free(mbo, coherent_buf_size);
-+ else
-+ kfree(mbo->virt_address);
- kfree(mbo);
- if (atomic_sub_and_test(1, &c->mbo_ref))
- complete(&c->cleanup);
-@@ -1289,10 +1291,13 @@ static int arm_mbo_chain(struct most_c_obj *c, int dir,
- 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 (c->iface->dma_alloc) {
-+ mbo->virt_address =
-+ c->iface->dma_alloc(mbo, coherent_buf_size);
-+ } else {
-+ mbo->virt_address =
-+ kzalloc(coherent_buf_size, GFP_KERNEL);
-+ }
- if (!mbo->virt_address) {
- pr_info("WARN: No DMA coherent buffer.\n");
- retval = i;
---
-2.7.4
-
diff --git a/recipes-kernel/most/files/0001-src-most-net-add-skb_put_data-function.patch b/recipes-kernel/most/files/0001-src-most-net-add-skb_put_data-function.patch
new file mode 100644
index 000000000..b9ef59515
--- /dev/null
+++ b/recipes-kernel/most/files/0001-src-most-net-add-skb_put_data-function.patch
@@ -0,0 +1,33 @@
+From d297f3ec0c45a6cfff6d83d8f0eb1c4a5ed0b95f Mon Sep 17 00:00:00 2001
+From: Christian Gromm <christian.gromm@microchip.com>
+Date: Thu, 9 Nov 2017 11:31:27 +0100
+Subject: [PATCH 1/2] src: most: net: add skb_put_data function
+
+This patch adds the function skb_put_data. It is needed to backport
+the sources to kernel versions prior to 4.13.
+
+Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
+---
+ driver/aim-network/networking.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/aim-network/networking.c b/aim-network/networking.c
+index 936f013..9c3d1eb 100644
+--- a/aim-network/networking.c
++++ b/aim-network/networking.c
+@@ -419,6 +419,12 @@ put_nd:
+ return 0;
+ }
+
++static inline void skb_put_data(struct sk_buff *skb, const void *data,
++ unsigned int len)
++{
++ memcpy(skb_put(skb, len), data, len);
++}
++
+ static int aim_rx_data(struct mbo *mbo)
+ {
+ const u32 zero = 0;
+--
+2.7.4
+
diff --git a/recipes-kernel/most/files/0002-most-pass-parent-devcie-to-snd_card_new.patch b/recipes-kernel/most/files/0002-most-pass-parent-devcie-to-snd_card_new.patch
deleted file mode 100644
index 2e341dd94..000000000
--- a/recipes-kernel/most/files/0002-most-pass-parent-devcie-to-snd_card_new.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-From c4a379b4d3058b153832991ba1a1d697cad06600 Mon Sep 17 00:00:00 2001
-From: Christian Gromm <christian.gromm@microchip.com>
-Date: Fri, 1 Sep 2017 13:53:32 +0200
-Subject: [PATCH 2/5] most: pass parent devcie to snd_card_new
-
-Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
----
- driver/aim-sound/sound.c | 2 +-
- driver/hdm-usb/hdm_usb.c | 1 +
- driver/include/mostcore.h | 1 +
- 3 files changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/aim-sound/sound.c b/aim-sound/sound.c
-index e4198e5..a2ccc79 100644
---- a/aim-sound/sound.c
-+++ b/aim-sound/sound.c
-@@ -595,7 +595,7 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id,
- return ret;
- }
-
-- ret = snd_card_new(NULL, -1, card_name, THIS_MODULE,
-+ ret = snd_card_new(iface->dev, -1, card_name, THIS_MODULE,
- sizeof(*channel), &card);
- if (ret < 0)
- return ret;
-diff --git a/hdm-usb/hdm_usb.c b/hdm-usb/hdm_usb.c
-index 0b689b5..0937496 100644
---- a/hdm-usb/hdm_usb.c
-+++ b/hdm-usb/hdm_usb.c
-@@ -1160,6 +1160,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
- mdev->iface.dma_free = hdm_dma_free;
- mdev->iface.description = mdev->description;
- mdev->iface.num_channels = num_endpoints;
-+ mdev->iface.dev = &interface->dev;
-
- snprintf(mdev->description, sizeof(mdev->description),
- "usb_device %d-%s:%d.%d",
-diff --git a/include/mostcore.h b/include/mostcore.h
-index deefe25..d3523a9 100644
---- a/include/mostcore.h
-+++ b/include/mostcore.h
-@@ -237,6 +237,7 @@ struct mbo {
- */
- struct most_interface {
- struct module *mod;
-+ struct device *dev;
- enum most_interface_type interface;
- const char *description;
- int num_channels;
---
-2.7.4
-
diff --git a/recipes-kernel/most/files/0002-src-most-add-auto-conf-feature.patch b/recipes-kernel/most/files/0002-src-most-add-auto-conf-feature.patch
new file mode 100644
index 000000000..dd811c81b
--- /dev/null
+++ b/recipes-kernel/most/files/0002-src-most-add-auto-conf-feature.patch
@@ -0,0 +1,472 @@
+From 9cb7cb85f59509ac445116e9458c502cf6cb74e6 Mon Sep 17 00:00:00 2001
+From: Christian Gromm <christian.gromm@microchip.com>
+Date: Thu, 9 Nov 2017 13:20:23 +0100
+Subject: [PATCH 2/2] src: most: add auto conf feature
+
+This patch adds the auto configuration feature to the driver
+sources. It is needed to have the driver configured automatically
+upon start up w/o the need for userspace to set up sysfs.
+
+Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
+---
+ driver/Makefile | 3 +
+ driver/default_conf.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++
+ driver/include/mostcore.h | 64 ++++++++++++++++++
+ driver/mostcore/core.c | 120 ++++++++++++++++++++++++++++------
+ 4 files changed, 331 insertions(+), 18 deletions(-)
+ create mode 100644 driver/default_conf.c
+
+diff --git a/Makefile b/Makefile
+index e77a4b6..6d74ebe 100644
+--- a/Makefile
++++ b/Makefile
+@@ -6,6 +6,9 @@ obj-m := mostcore.o
+ mostcore-y := mostcore/core.o
+ CFLAGS_core.o := -I$(src)/include/
+
++obj-m += default_conf.o
++CFLAGL_default_conf.o := -I$(src)/include
++
+ obj-m += aim_cdev.o
+ aim_cdev-y := aim-cdev/cdev.o
+ CFLAGS_cdev.o := -I$(src)/include/
+diff --git a/default_conf.c b/default_conf.c
+new file mode 100644
+index 0000000..adb1786
+--- /dev/null
++++ b/default_conf.c
+@@ -0,0 +1,162 @@
++/*
++ * default_conf.c - Default configuration for the MOST channels.
++ *
++ * Copyright (C) 2017, 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.
++ */
++
++#include "include/mostcore.h"
++#include <linux/module.h>
++
++static struct most_config_probe config_probes[] = {
++
++ /* OS81118 Control */
++ {
++ .ch_name = "ep8f",
++ .cfg = {
++ .direction = MOST_CH_RX,
++ .data_type = MOST_CH_CONTROL,
++ .num_buffers = 16,
++ .buffer_size = 64,
++ },
++ .aim_name = "cdev",
++ .aim_param = "inic-usb-crx",
++ },
++ {
++ .ch_name = "ep0f",
++ .cfg = {
++ .direction = MOST_CH_TX,
++ .data_type = MOST_CH_CONTROL,
++ .num_buffers = 16,
++ .buffer_size = 64,
++ },
++ .aim_name = "cdev",
++ .aim_param = "inic-usb-ctx",
++ },
++ /* OS81118 Async */
++ {
++ .ch_name = "ep8e",
++ .cfg = {
++ .direction = MOST_CH_RX,
++ .data_type = MOST_CH_ASYNC,
++ .num_buffers = 20,
++ .buffer_size = 1522,
++ },
++ .aim_name = "networking",
++ .aim_param = "inic-usb-arx",
++ },
++ {
++ .ch_name = "ep0e",
++ .cfg = {
++ .direction = MOST_CH_TX,
++ .data_type = MOST_CH_ASYNC,
++ .num_buffers = 20,
++ .buffer_size = 1522,
++ },
++ .aim_name = "networking",
++ .aim_param = "inic-usb-atx",
++ },
++ /* OS81210 Control */
++ {
++ .ch_name = "ep87",
++ .cfg = {
++ .direction = MOST_CH_RX,
++ .data_type = MOST_CH_CONTROL,
++ .num_buffers = 16,
++ .buffer_size = 64,
++ },
++ .aim_name = "cdev",
++ .aim_param = "inic-usb-crx",
++ },
++ {
++ .ch_name = "ep07",
++ .cfg = {
++ .direction = MOST_CH_TX,
++ .data_type = MOST_CH_CONTROL,
++ .num_buffers = 16,
++ .buffer_size = 64,
++ },
++ .aim_name = "cdev",
++ .aim_param = "inic-usb-ctx",
++ },
++ /* OS81210 Async */
++ {
++ .ch_name = "ep86",
++ .cfg = {
++ .direction = MOST_CH_RX,
++ .data_type = MOST_CH_ASYNC,
++ .num_buffers = 20,
++ .buffer_size = 1522,
++ },
++ .aim_name = "networking",
++ .aim_param = "inic-usb-arx",
++ },
++ {
++ .ch_name = "ep06",
++ .cfg = {
++ .direction = MOST_CH_TX,
++ .data_type = MOST_CH_ASYNC,
++ .num_buffers = 20,
++ .buffer_size = 1522,
++ },
++ .aim_name = "networking",
++ .aim_param = "inic-usb-atx",
++ },
++ /* Streaming channels (common for all INICs) */
++ {
++ .ch_name = "ep01",
++ .cfg = {
++ .direction = MOST_CH_TX,
++ .data_type = MOST_CH_SYNC,
++ .num_buffers = 8,
++ .buffer_size = 2 * 12 * 42,
++ .subbuffer_size = 12,
++ .packets_per_xact = 42,
++ },
++ .aim_name = "sound",
++ .aim_param = "ep01-6ch.6x16",
++ },
++ {
++ .ch_name = "ep02",
++ .cfg = {
++ .direction = MOST_CH_TX,
++ .data_type = MOST_CH_ISOC,
++ .num_buffers = 8,
++ .buffer_size = 40 * 188,
++ .subbuffer_size = 188,
++ .packets_per_xact = 2,
++ },
++ .aim_name = "cdev",
++ .aim_param = "inic-usb-itx1",
++ },
++
++ /* sentinel */
++ {}
++};
++
++static struct most_config_set config_set = {
++ .probes = config_probes
++};
++
++static int __init mod_init(void)
++{
++ most_register_config_set(&config_set);
++ return 0;
++}
++
++static void __exit mod_exit(void)
++{
++ most_deregister_config_set(&config_set);
++}
++
++module_init(mod_init);
++module_exit(mod_exit);
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
++MODULE_DESCRIPTION("Default configuration for the MOST channels");
+diff --git a/include/mostcore.h b/include/mostcore.h
+index dc87121..3c00efb 100644
+--- a/include/mostcore.h
++++ b/include/mostcore.h
+@@ -145,6 +145,39 @@ struct most_channel_config {
+ u16 dbr_size;
+ };
+
++/**
++ * struct most_config_probe - matching rule, channel configuration and
++ * the optional AIM name used for the automatic configuration and linking
++ * of the channel
++ * @dev_name: optional matching device id
++ * ("usb_device 1-1:1.0," "dim2-12345678", etc.)
++ * @ch_name: matching channel name ("ep8f", "ca2", etc.)
++ * @cfg: configuration that will be applied for the found channel
++ * @aim_name: optional name of the AIM that will be linked to the channel
++ * ("cdev", "networking", "v4l", "sound")
++ * @aim_param: AIM dependent parameter (it is the character device name
++ * for the cdev AIM, PCM format for the audio AIM, etc.)
++ */
++struct most_config_probe {
++ const char *dev_name;
++ const char *ch_name;
++ struct most_channel_config cfg;
++ const char *aim_name;
++ const char *aim_param;
++};
++
++/**
++ * struct most_config_set - the configuration set containing
++ * several automatic configurations for the different channels
++ * @probes: list of the matching rules and the configurations,
++ * that must be ended with the empty structure
++ * @list: list head used by the MostCore
++ */
++struct most_config_set {
++ const struct most_config_probe *probes;
++ struct list_head list;
++};
++
+ /*
+ * struct mbo - MOST Buffer Object.
+ * @context: context for core completion handler
+@@ -285,6 +318,37 @@ struct most_aim {
+ };
+
+ /**
++ * most_register_config_set - registers the configuration set
++ *
++ * @cfg_set: configuration set to be registered for the future probes
++ *
++ * The function registers the given configuration set.
++ *
++ * It is possible to register or deregister several configuration sets
++ * independently. Different configuration sets may contain the
++ * overlapped matching rules but later registered configuration set has
++ * the higher priority over the prior registered set.
++ *
++ * The only the first matched configuration is applied for each
++ * channel.
++ *
++ * The configuration for the channel is applied at the time of
++ * registration of the parent most_interface.
++ */
++void most_register_config_set(struct most_config_set *cfg_set);
++
++/**
++ * most_deregister_config_set - deregisters the prior registered
++ * configuration set
++ *
++ * @cfg_set: configuration set to be deregistered
++ *
++ * The calling of this function does not change the current
++ * configuration of the channels.
++ */
++void most_deregister_config_set(struct most_config_set *cfg_set);
++
++/**
+ * most_register_interface - Registers instance of the interface.
+ * @iface: Pointer to the interface instance description.
+ *
+diff --git a/mostcore/core.c b/mostcore/core.c
+index 9e0a352..6035cf0 100644
+--- a/mostcore/core.c
++++ b/mostcore/core.c
+@@ -36,6 +36,8 @@ static struct class *most_class;
+ static struct device *core_dev;
+ static struct ida mdev_id;
+ static int dummy_num_buffers;
++static struct list_head config_probes;
++struct mutex config_probes_mt; /* config_probes */
+
+ struct most_c_aim_obj {
+ struct most_aim *ptr;
+@@ -918,6 +920,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, &c->kobj, 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
+@@ -946,45 +972,33 @@ static ssize_t add_link_store(struct most_aim_obj *aim_obj,
+ 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 *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_param);
+ if (ret)
+ return ret;
+
+- if (!mdev_devnod || *mdev_devnod == 0) {
++ 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;
+
+- 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_obj->driver, aim_param);
++ if (ret)
+ return ret;
+- }
+
+ return len;
+ }
+@@ -1679,6 +1693,73 @@ int most_deregister_aim(struct most_aim *aim)
+ }
+ EXPORT_SYMBOL_GPL(most_deregister_aim);
+
++void most_register_config_set(struct most_config_set *cfg_set)
++{
++ mutex_lock(&config_probes_mt);
++ list_add(&cfg_set->list, &config_probes);
++ mutex_unlock(&config_probes_mt);
++}
++EXPORT_SYMBOL(most_register_config_set);
++
++void most_deregister_config_set(struct most_config_set *cfg_set)
++{
++ mutex_lock(&config_probes_mt);
++ list_del(&cfg_set->list);
++ mutex_unlock(&config_probes_mt);
++}
++EXPORT_SYMBOL(most_deregister_config_set);
++
++static int probe_aim(struct most_c_obj *c,
++ const char *aim_name, const char *aim_param)
++{
++ struct most_aim_obj *aim_obj;
++ char buf[STRING_SIZE];
++
++ list_for_each_entry(aim_obj, &aim_list, list) {
++ if (!strcmp(aim_obj->driver->name, aim_name)) {
++ strlcpy(buf, aim_param ? aim_param : "", sizeof(buf));
++ return link_channel_to_aim(c, aim_obj->driver, buf);
++ }
++ }
++ return 0;
++}
++
++static bool probe_config_set(struct most_c_obj *c,
++ const char *dev_name, const char *ch_name,
++ const struct most_config_probe *p)
++{
++ int err;
++
++ for (; p->ch_name; p++) {
++ if ((p->dev_name && strcmp(dev_name, p->dev_name)) ||
++ strcmp(ch_name, p->ch_name))
++ continue;
++
++ c->cfg = p->cfg;
++ if (p->aim_name) {
++ err = probe_aim(c, p->aim_name, p->aim_param);
++ if (err)
++ pr_err("failed to autolink %s to %s: %d\n",
++ ch_name, p->aim_name, err);
++ }
++ return true;
++ }
++ return false;
++}
++
++static void find_configuration(struct most_c_obj *c, const char *dev_name,
++ const char *ch_name)
++{
++ struct most_config_set *plist;
++
++ mutex_lock(&config_probes_mt);
++ list_for_each_entry(plist, &config_probes, list) {
++ if (probe_config_set(c, dev_name, ch_name, plist->probes))
++ break;
++ }
++ mutex_unlock(&config_probes_mt);
++}
++
+ /**
+ * most_register_interface - registers an interface with core
+ * @iface: pointer to the instance of the interface description.
+@@ -1777,6 +1858,7 @@ struct kobject *most_register_interface(struct most_interface *iface)
+ mutex_init(&c->start_mutex);
+ mutex_init(&c->nq_mutex);
+ list_add_tail(&c->list, &inst->channel_list);
++ find_configuration(c, iface->description, channel_name);
+ }
+ pr_info("registered new MOST device mdev%d (%s)\n",
+ inst->dev_id, iface->description);
+@@ -1880,6 +1962,8 @@ static int __init most_init(void)
+ pr_info("init()\n");
+ INIT_LIST_HEAD(&instance_list);
+ INIT_LIST_HEAD(&aim_list);
++ INIT_LIST_HEAD(&config_probes);
++ mutex_init(&config_probes_mt);
+ ida_init(&mdev_id);
+
+ err = bus_register(&most_bus);
+--
+2.7.4
+