diff options
Diffstat (limited to 'drivers/staging/most')
30 files changed, 1191 insertions, 260 deletions
diff --git a/drivers/staging/most/Documentation/ABI/configfs-most.txt b/drivers/staging/most/Documentation/ABI/configfs-most.txt new file mode 100644 index 000000000000..25b3e18c4d91 --- /dev/null +++ b/drivers/staging/most/Documentation/ABI/configfs-most.txt @@ -0,0 +1,204 @@ +What: /sys/kernel/config/most_<component> +Date: March 8, 2019 +KernelVersion: 5.2 +Description: Interface is used to configure and connect device channels + to component drivers. + + Attributes are visible only when configfs is mounted. To mount + configfs in /sys/kernel/config directory use: + # mount -t configfs none /sys/kernel/config/ + + +What: /sys/kernel/config/most_cdev/<link> +Date: March 8, 2019 +KernelVersion: 5.2 +Description: + The attributes: + + buffer_size configure the buffer size for this channel + + subbuffer_size configure the sub-buffer size for this channel + (needed for synchronous and isochrnous data) + + + num_buffers configure number of buffers used for this + channel + + datatype configure type of data that will travel over + this channel + + direction configure whether this link will be an input + or output + + dbr_size configure DBR data buffer size (this is used + for MediaLB communiction only) + + packets_per_xact + configure the number of packets that will be + collected from the network before being + transmitted via USB (this is used for USB + communiction only) + + device name of the device the link is to be attached to + + channel name of the channel the link is to be attached to + + comp_params pass parameters needed by some components + + create_link write '1' to this attribute to trigger the + creation of the link. In case of speculative + configuration, the creation is post-poned until + a physical device is being attached to the bus. + + destroy_link write '1' to this attribute to destroy an + active link + +What: /sys/kernel/config/most_video/<link> +Date: March 8, 2019 +KernelVersion: 5.2 +Description: + The attributes: + + buffer_size configure the buffer size for this channel + + subbuffer_size configure the sub-buffer size for this channel + (needed for synchronous and isochrnous data) + + + num_buffers configure number of buffers used for this + channel + + datatype configure type of data that will travel over + this channel + + direction configure whether this link will be an input + or output + + dbr_size configure DBR data buffer size (this is used + for MediaLB communiction only) + + packets_per_xact + configure the number of packets that will be + collected from the network before being + transmitted via USB (this is used for USB + communiction only) + + device name of the device the link is to be attached to + + channel name of the channel the link is to be attached to + + comp_params pass parameters needed by some components + + create_link write '1' to this attribute to trigger the + creation of the link. In case of speculative + configuration, the creation is post-poned until + a physical device is being attached to the bus. + + destroy_link write '1' to this attribute to destroy an + active link + +What: /sys/kernel/config/most_net/<link> +Date: March 8, 2019 +KernelVersion: 5.2 +Description: + The attributes: + + buffer_size configure the buffer size for this channel + + subbuffer_size configure the sub-buffer size for this channel + (needed for synchronous and isochrnous data) + + + num_buffers configure number of buffers used for this + channel + + datatype configure type of data that will travel over + this channel + + direction configure whether this link will be an input + or output + + dbr_size configure DBR data buffer size (this is used + for MediaLB communiction only) + + packets_per_xact + configure the number of packets that will be + collected from the network before being + transmitted via USB (this is used for USB + communiction only) + + device name of the device the link is to be attached to + + channel name of the channel the link is to be attached to + + comp_params pass parameters needed by some components + + create_link write '1' to this attribute to trigger the + creation of the link. In case of speculative + configuration, the creation is post-poned until + a physical device is being attached to the bus. + + destroy_link write '1' to this attribute to destroy an + active link + +What: /sys/kernel/config/most_sound/<card> +Date: March 8, 2019 +KernelVersion: 5.2 +Description: + The attributes: + + create_card write '1' to this attribute to trigger the + registration of the sound card with the ALSA + subsystem. + +What: /sys/kernel/config/most_sound/<card>/<link> +Date: March 8, 2019 +KernelVersion: 5.2 +Description: + The attributes: + + buffer_size configure the buffer size for this channel + + subbuffer_size configure the sub-buffer size for this channel + (needed for synchronous and isochrnous data) + + + num_buffers configure number of buffers used for this + channel + + datatype configure type of data that will travel over + this channel + + direction configure whether this link will be an input + or output + + dbr_size configure DBR data buffer size (this is used + for MediaLB communiction only) + + packets_per_xact + configure the number of packets that will be + collected from the network before being + transmitted via USB (this is used for USB + communiction only) + + device name of the device the link is to be attached to + + channel name of the channel the link is to be attached to + + comp_params pass parameters needed by some components + + create_link write '1' to this attribute to trigger the + creation of the link. In case of speculative + configuration, the creation is post-poned until + a physical device is being attached to the bus. + + destroy_link write '1' to this attribute to destroy an + active link + +What: /sys/kernel/config/rdma_cm/<hca>/ports/<port-num>/default_roce_tos +Date: March 8, 2019 +KernelVersion: 5.2 +Description: RDMA-CM QPs from HCA <hca> at port <port-num> + will be created with this TOS as default. + This can be overridden by using the rdma_set_option API. + The possible RoCE TOS values are 0-255. diff --git a/drivers/staging/most/Documentation/driver_usage.txt b/drivers/staging/most/Documentation/driver_usage.txt index da7a8f405b9b..56d79195bb3c 100644 --- a/drivers/staging/most/Documentation/driver_usage.txt +++ b/drivers/staging/most/Documentation/driver_usage.txt @@ -115,36 +115,75 @@ following components are available Section 2 Usage of the MOST Driver - Section 2.1 Configuration - -See ABI/sysfs-bus-most.txt - - - Section 2.2 Routing Channels - -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: - - "device_name:channel_name:component_name:link_name[.param]" - -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. - -Cdev component example: - $ echo "mdev0:ep_81:cdev:my_rx_channel" >$(DRV_DIR)/add_link - - -Sound component example: - -The sound component needs additional parameters to determine the audio -resolution that is going to be used and to trigger the registration of a -sound card with ALSA. The following audio formats are available: + Section 2.1 Configuration and Data Link + +The driver is to be configured via configfs. Each loaded component kernel +object (see section 1.3) registers a subsystem with configfs, which is used to +configure and establish communiction pathways (links) to attached devices on +the bus. To do so, the user has to descend into the component's configuration +directory and create a new directory (child config itmes). The name of this +directory will be used as a reference for the link and it will contain the +following attributes: + + - buffer_size + configure the buffer size for this channel + - subbuffer_size + configure the sub-buffer size for this channel (needed for + synchronous and isochrnous data) + - num_buffers + configure number of buffers used for this channel + - datatype + configure type of data that will travel over this channel + - direction + configure whether this link will be an input or output + - dbr_size + configure DBR data buffer size (this is used for MediaLB communiction + only) + - packets_per_xact + configure the number of packets that will be collected from the + network before being transmitted via USB (this is used for USB + communiction only) + - device + name of the device the link is to be attached to + - channel + name of the channel the link is to be attached to + - comp_params + pass parameters needed by some components + - create_link + write '1' to this attribute to trigger the creation of the link. In + case of speculative configuration, the creation is post-poned until + a physical device is being attached to the bus. + - destroy_link + write '1' to this attribute to destroy an already established link + + +See ABI/sysfs-bus-most.txt and ABI/configfs-most.txt + + + Section 2.2 Configure a Sound Card + +Setting up synchronous channels to be mapped as an ALSA sound adapter is a two +step process. Firstly, a directory (child config group) has to be created +inside the most_sound's configuration directory. This adapter dir will +represent the sound adapter. The name of the directory is for user reference +only and has no further influence, as all sound adapters will be given a static +name in ALSA. The sound adapter will have the following attribute: + + - create_card + write '1' to this attribute to trigger the registration of the card + with the ALSA subsystem. + In case of speculative configuration, the creation is post-poned + until a physical device is being attached to the bus. + +Secondly, links will have to be created inside the adapter dir as described in +section 2.1. These links will become the PCM devices of the sound card. The +name of a PCM device will be inherited from the directory name. When all +channels have been configured and created, the sound card itself can be created +by writing '1' to the create_card attribute. + +The sound component needs an additional parameter to determine the audio +resolution that is going to be used. +The following audio formats are available: - "1x8" (Mono) - "2x16" (16-bit stereo) @@ -152,18 +191,8 @@ sound card with ALSA. The following audio formats are available: - "2x32" (32-bit stereo) - "6x16" (16-bit surround 5.1) -To make the sound module create a sound card and register it with ALSA the -string "create" needs to be attached to the module parameter section of the -configuration string. To create a sound card with with two playback devices -(linked to channel ep01 and ep02) and one capture device (linked to channel -ep83) the following is written to the add_link file: - - $ echo "mdev0:ep01:sound:most51_playback.6x16" >$(DRV_DIR)/add_link - $ echo "mdev0:ep02:sound:most_playback.2x16" >$(DRV_DIR)/add_link - $ echo "mdev0:ep83:sound:most_capture.2x16.create" >$(DRV_DIR)/add_link - -The link names (most51_playback, most_playback and most_capture) will -become the names of the PCM devices of the sound card. +The resolution string has to be written to the link directory's comp_params +attribute. Section 2.3 USB Padding @@ -174,13 +203,13 @@ 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'. +written to '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'. The driver, then, calculates the synchronous threshold as follows: - frame_size = set_subbuffer_size * packets_per_xact + frame_size = 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 @@ -192,15 +221,15 @@ 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 +written to 'subbuffer_size' and hardware will always expect two isochronous +packets within one USB transaction. This renders - MTU_USB - (2 * set_subbuffer_size) + MTU_USB - (2 * subbuffer_size) bytes for padding. -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 +Note that at least (2 * subbuffer_size) bytes for isochronous data or +(subbuffer_size * packts_per_xact) bytes for synchronous data need to be put in the transmission buffer and passed to the driver. Since adapter drivers are allowed to change a chosen configuration to best diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig index 20047abbe560..db32ea7d1743 100644 --- a/drivers/staging/most/Kconfig +++ b/drivers/staging/most/Kconfig @@ -1,6 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 menuconfig MOST tristate "MOST support" - depends on HAS_DMA + depends on HAS_DMA && CONFIGFS_FS default n ---help--- Say Y here if you want to enable MOST support. diff --git a/drivers/staging/most/Makefile b/drivers/staging/most/Makefile index c7662f65f6db..85ea5a434ced 100644 --- a/drivers/staging/most/Makefile +++ b/drivers/staging/most/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MOST) += most_core.o most_core-y := core.o +most_core-y += configfs.o ccflags-y += -I $(srctree)/drivers/staging/ obj-$(CONFIG_MOST_CDEV) += cdev/ diff --git a/drivers/staging/most/cdev/Kconfig b/drivers/staging/most/cdev/Kconfig index 2b04e26bcbea..330c95fe6550 100644 --- a/drivers/staging/most/cdev/Kconfig +++ b/drivers/staging/most/cdev/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # MOST Cdev configuration # diff --git a/drivers/staging/most/cdev/Makefile b/drivers/staging/most/cdev/Makefile index 21b0bd72c01d..9f4a8b8c9c27 100644 --- a/drivers/staging/most/cdev/Makefile +++ b/drivers/staging/most/cdev/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MOST_CDEV) += most_cdev.o most_cdev-objs := cdev.o diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index f2b347cda8b7..d0cc0b746107 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -425,7 +425,7 @@ static int comp_tx_completion(struct most_interface *iface, int channel_id) * Returns 0 on success or error code otherwise. */ static int comp_probe(struct most_interface *iface, int channel_id, - struct most_channel_config *cfg, char *name) + struct most_channel_config *cfg, char *name, char *args) { struct comp_channel *c; unsigned long cl_flags; @@ -527,8 +527,13 @@ static int __init mod_init(void) err = most_register_component(&comp.cc); if (err) goto free_cdev; + err = most_register_configfs_subsys(&comp.cc); + if (err) + goto deregister_comp; return 0; +deregister_comp: + most_deregister_component(&comp.cc); free_cdev: unregister_chrdev_region(comp.devno, CHRDEV_REGION_SIZE); dest_ida: @@ -543,13 +548,14 @@ static void __exit mod_exit(void) pr_info("exit module\n"); + most_deregister_configfs_subsys(&comp.cc); most_deregister_component(&comp.cc); list_for_each_entry_safe(c, tmp, &channel_list, list) { destroy_cdev(c); destroy_channel(c); } - unregister_chrdev_region(comp.devno, 1); + unregister_chrdev_region(comp.devno, CHRDEV_REGION_SIZE); ida_destroy(&comp.minor_id); class_destroy(comp.class); } diff --git a/drivers/staging/most/configfs.c b/drivers/staging/most/configfs.c new file mode 100644 index 000000000000..1d8bf29e0ffb --- /dev/null +++ b/drivers/staging/most/configfs.c @@ -0,0 +1,676 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * configfs.c - Implementation of configfs interface to the driver stack + * + * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/configfs.h> +#include <most/core.h> + +struct mdev_link { + struct config_item item; + struct list_head list; + bool create_link; + bool destroy_link; + u16 num_buffers; + u16 buffer_size; + u16 subbuffer_size; + u16 packets_per_xact; + u16 dbr_size; + char datatype[PAGE_SIZE]; + char direction[PAGE_SIZE]; + char name[PAGE_SIZE]; + char device[PAGE_SIZE]; + char channel[PAGE_SIZE]; + char comp[PAGE_SIZE]; + char comp_params[PAGE_SIZE]; +}; + +static struct list_head mdev_link_list; + +static int set_cfg_buffer_size(struct mdev_link *link) +{ + if (!link->buffer_size) + return -ENODATA; + return most_set_cfg_buffer_size(link->device, link->channel, + link->buffer_size); +} + +static int set_cfg_subbuffer_size(struct mdev_link *link) +{ + if (!link->subbuffer_size) + return -ENODATA; + return most_set_cfg_subbuffer_size(link->device, link->channel, + link->subbuffer_size); +} + +static int set_cfg_dbr_size(struct mdev_link *link) +{ + if (!link->dbr_size) + return -ENODATA; + return most_set_cfg_dbr_size(link->device, link->channel, + link->dbr_size); +} + +static int set_cfg_num_buffers(struct mdev_link *link) +{ + if (!link->num_buffers) + return -ENODATA; + return most_set_cfg_num_buffers(link->device, link->channel, + link->num_buffers); +} + +static int set_cfg_packets_xact(struct mdev_link *link) +{ + if (!link->packets_per_xact) + return -ENODATA; + return most_set_cfg_packets_xact(link->device, link->channel, + link->packets_per_xact); +} + +static int set_cfg_direction(struct mdev_link *link) +{ + if (!strlen(link->direction)) + return -ENODATA; + return most_set_cfg_direction(link->device, link->channel, + link->direction); +} + +static int set_cfg_datatype(struct mdev_link *link) +{ + if (!strlen(link->datatype)) + return -ENODATA; + return most_set_cfg_datatype(link->device, link->channel, + link->datatype); +} + +static int (*set_config_val[])(struct mdev_link *link) = { + set_cfg_buffer_size, + set_cfg_subbuffer_size, + set_cfg_dbr_size, + set_cfg_num_buffers, + set_cfg_packets_xact, + set_cfg_direction, + set_cfg_datatype, +}; + +static struct mdev_link *to_mdev_link(struct config_item *item) +{ + return container_of(item, struct mdev_link, item); +} + +static int set_config_and_add_link(struct mdev_link *mdev_link) +{ + int i; + int ret; + + for (i = 0; i < ARRAY_SIZE(set_config_val); i++) { + ret = set_config_val[i](mdev_link); + if (ret < 0 && ret != -ENODEV) { + pr_err("Config failed\n"); + return ret; + } + } + + return most_add_link(mdev_link->device, mdev_link->channel, + mdev_link->comp, mdev_link->name, + mdev_link->comp_params); +} + +static ssize_t mdev_link_create_link_store(struct config_item *item, + const char *page, size_t count) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + bool tmp; + int ret; + + ret = kstrtobool(page, &tmp); + if (ret) + return ret; + if (!tmp) + return count; + ret = set_config_and_add_link(mdev_link); + if (ret && ret != -ENODEV) + return ret; + list_add_tail(&mdev_link->list, &mdev_link_list); + mdev_link->create_link = tmp; + return count; +} + +static ssize_t mdev_link_destroy_link_store(struct config_item *item, + const char *page, size_t count) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + bool tmp; + int ret; + + ret = kstrtobool(page, &tmp); + if (ret) + return ret; + if (!tmp) + return count; + mdev_link->destroy_link = tmp; + ret = most_remove_link(mdev_link->device, mdev_link->channel, + mdev_link->comp); + if (ret) + return ret; + if (!list_empty(&mdev_link_list)) + list_del(&mdev_link->list); + return count; +} + +static ssize_t mdev_link_direction_show(struct config_item *item, char *page) +{ + return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->direction); +} + +static ssize_t mdev_link_direction_store(struct config_item *item, + const char *page, size_t count) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + + if (!sysfs_streq(page, "dir_rx") && !sysfs_streq(page, "rx") && + !sysfs_streq(page, "dir_tx") && !sysfs_streq(page, "tx")) + return -EINVAL; + strcpy(mdev_link->direction, page); + return count; +} + +static ssize_t mdev_link_datatype_show(struct config_item *item, char *page) +{ + return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->datatype); +} + +static ssize_t mdev_link_datatype_store(struct config_item *item, + const char *page, size_t count) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + + if (!sysfs_streq(page, "control") && !sysfs_streq(page, "async") && + !sysfs_streq(page, "sync") && !sysfs_streq(page, "isoc") && + !sysfs_streq(page, "isoc_avp")) + return -EINVAL; + strcpy(mdev_link->datatype, page); + return count; +} + +static ssize_t mdev_link_device_show(struct config_item *item, char *page) +{ + return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->device); +} + +static ssize_t mdev_link_device_store(struct config_item *item, + const char *page, size_t count) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + + strcpy(mdev_link->device, page); + return count; +} + +static ssize_t mdev_link_channel_show(struct config_item *item, char *page) +{ + return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->channel); +} + +static ssize_t mdev_link_channel_store(struct config_item *item, + const char *page, size_t count) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + + strcpy(mdev_link->channel, page); + return count; +} + +static ssize_t mdev_link_comp_show(struct config_item *item, char *page) +{ + return snprintf(page, PAGE_SIZE, "%s\n", to_mdev_link(item)->comp); +} + +static ssize_t mdev_link_comp_store(struct config_item *item, + const char *page, size_t count) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + + strcpy(mdev_link->comp, page); + return count; +} + +static ssize_t mdev_link_comp_params_show(struct config_item *item, char *page) +{ + return snprintf(page, PAGE_SIZE, "%s\n", + to_mdev_link(item)->comp_params); +} + +static ssize_t mdev_link_comp_params_store(struct config_item *item, + const char *page, size_t count) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + + strcpy(mdev_link->comp_params, page); + return count; +} + +static ssize_t mdev_link_num_buffers_show(struct config_item *item, char *page) +{ + return snprintf(page, PAGE_SIZE, "%d\n", + to_mdev_link(item)->num_buffers); +} + +static ssize_t mdev_link_num_buffers_store(struct config_item *item, + const char *page, size_t count) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + int ret; + + ret = kstrtou16(page, 0, &mdev_link->num_buffers); + if (ret) + return ret; + return count; +} + +static ssize_t mdev_link_buffer_size_show(struct config_item *item, char *page) +{ + return snprintf(page, PAGE_SIZE, "%d\n", + to_mdev_link(item)->buffer_size); +} + +static ssize_t mdev_link_buffer_size_store(struct config_item *item, + const char *page, size_t count) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + int ret; + + ret = kstrtou16(page, 0, &mdev_link->buffer_size); + if (ret) + return ret; + return count; +} + +static ssize_t mdev_link_subbuffer_size_show(struct config_item *item, + char *page) +{ + return snprintf(page, PAGE_SIZE, "%d\n", + to_mdev_link(item)->subbuffer_size); +} + +static ssize_t mdev_link_subbuffer_size_store(struct config_item *item, + const char *page, size_t count) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + int ret; + + ret = kstrtou16(page, 0, &mdev_link->subbuffer_size); + if (ret) + return ret; + return count; +} + +static ssize_t mdev_link_packets_per_xact_show(struct config_item *item, + char *page) +{ + return snprintf(page, PAGE_SIZE, "%d\n", + to_mdev_link(item)->packets_per_xact); +} + +static ssize_t mdev_link_packets_per_xact_store(struct config_item *item, + const char *page, size_t count) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + int ret; + + ret = kstrtou16(page, 0, &mdev_link->packets_per_xact); + if (ret) + return ret; + return count; +} + +static ssize_t mdev_link_dbr_size_show(struct config_item *item, char *page) +{ + return snprintf(page, PAGE_SIZE, "%d\n", to_mdev_link(item)->dbr_size); +} + +static ssize_t mdev_link_dbr_size_store(struct config_item *item, + const char *page, size_t count) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + int ret; + + ret = kstrtou16(page, 0, &mdev_link->dbr_size); + if (ret) + return ret; + return count; +} + +CONFIGFS_ATTR_WO(mdev_link_, create_link); +CONFIGFS_ATTR_WO(mdev_link_, destroy_link); +CONFIGFS_ATTR(mdev_link_, device); +CONFIGFS_ATTR(mdev_link_, channel); +CONFIGFS_ATTR(mdev_link_, comp); +CONFIGFS_ATTR(mdev_link_, comp_params); +CONFIGFS_ATTR(mdev_link_, num_buffers); +CONFIGFS_ATTR(mdev_link_, buffer_size); +CONFIGFS_ATTR(mdev_link_, subbuffer_size); +CONFIGFS_ATTR(mdev_link_, packets_per_xact); +CONFIGFS_ATTR(mdev_link_, datatype); +CONFIGFS_ATTR(mdev_link_, direction); +CONFIGFS_ATTR(mdev_link_, dbr_size); + +static struct configfs_attribute *mdev_link_attrs[] = { + &mdev_link_attr_create_link, + &mdev_link_attr_destroy_link, + &mdev_link_attr_device, + &mdev_link_attr_channel, + &mdev_link_attr_comp, + &mdev_link_attr_comp_params, + &mdev_link_attr_num_buffers, + &mdev_link_attr_buffer_size, + &mdev_link_attr_subbuffer_size, + &mdev_link_attr_packets_per_xact, + &mdev_link_attr_datatype, + &mdev_link_attr_direction, + &mdev_link_attr_dbr_size, + NULL, +}; + +static void mdev_link_release(struct config_item *item) +{ + struct mdev_link *mdev_link = to_mdev_link(item); + int ret; + + if (!list_empty(&mdev_link_list)) { + ret = most_remove_link(mdev_link->device, mdev_link->channel, + mdev_link->comp); + if (ret && (ret != -ENODEV)) + pr_err("Removing link failed.\n"); + list_del(&mdev_link->list); + } + kfree(to_mdev_link(item)); +} + +static struct configfs_item_operations mdev_link_item_ops = { + .release = mdev_link_release, +}; + +static const struct config_item_type mdev_link_type = { + .ct_item_ops = &mdev_link_item_ops, + .ct_attrs = mdev_link_attrs, + .ct_owner = THIS_MODULE, +}; + +struct most_common { + struct config_group group; +}; + +static struct most_common *to_most_common(struct config_item *item) +{ + return container_of(to_config_group(item), struct most_common, group); +} + +static struct config_item *most_common_make_item(struct config_group *group, + const char *name) +{ + struct mdev_link *mdev_link; + + mdev_link = kzalloc(sizeof(*mdev_link), GFP_KERNEL); + if (!mdev_link) + return ERR_PTR(-ENOMEM); + + config_item_init_type_name(&mdev_link->item, name, + &mdev_link_type); + + if (!strcmp(group->cg_item.ci_namebuf, "most_cdev")) + strcpy(mdev_link->comp, "cdev"); + else if (!strcmp(group->cg_item.ci_namebuf, "most_net")) + strcpy(mdev_link->comp, "net"); + else if (!strcmp(group->cg_item.ci_namebuf, "most_video")) + strcpy(mdev_link->comp, "video"); + strcpy(mdev_link->name, name); + return &mdev_link->item; +} + +static void most_common_release(struct config_item *item) +{ + kfree(to_most_common(item)); +} + +static struct configfs_item_operations most_common_item_ops = { + .release = most_common_release, +}; + +static struct configfs_group_operations most_common_group_ops = { + .make_item = most_common_make_item, +}; + +static const struct config_item_type most_common_type = { + .ct_item_ops = &most_common_item_ops, + .ct_group_ops = &most_common_group_ops, + .ct_owner = THIS_MODULE, +}; + +static struct configfs_subsystem most_cdev_subsys = { + .su_group = { + .cg_item = { + .ci_namebuf = "most_cdev", + .ci_type = &most_common_type, + }, + }, +}; + +static struct configfs_subsystem most_net_subsys = { + .su_group = { + .cg_item = { + .ci_namebuf = "most_net", + .ci_type = &most_common_type, + }, + }, +}; + +static struct configfs_subsystem most_video_subsys = { + .su_group = { + .cg_item = { + .ci_namebuf = "most_video", + .ci_type = &most_common_type, + }, + }, +}; + +struct most_snd_grp { + struct config_group group; + bool create_card; + struct list_head list; +}; + +static struct most_snd_grp *to_most_snd_grp(struct config_item *item) +{ + return container_of(to_config_group(item), struct most_snd_grp, group); +} + +static struct config_item *most_snd_grp_make_item(struct config_group *group, + const char *name) +{ + struct mdev_link *mdev_link; + + mdev_link = kzalloc(sizeof(*mdev_link), GFP_KERNEL); + if (!mdev_link) + return ERR_PTR(-ENOMEM); + + config_item_init_type_name(&mdev_link->item, name, &mdev_link_type); + mdev_link->create_link = 0; + strcpy(mdev_link->name, name); + strcpy(mdev_link->comp, "sound"); + return &mdev_link->item; +} + +static ssize_t most_snd_grp_create_card_store(struct config_item *item, + const char *page, size_t count) +{ + struct most_snd_grp *snd_grp = to_most_snd_grp(item); + int ret; + bool tmp; + + ret = kstrtobool(page, &tmp); + if (ret) + return ret; + if (tmp) { + ret = most_cfg_complete("sound"); + if (ret) + return ret; + } + snd_grp->create_card = tmp; + return count; +} + +CONFIGFS_ATTR_WO(most_snd_grp_, create_card); + +static struct configfs_attribute *most_snd_grp_attrs[] = { + &most_snd_grp_attr_create_card, + NULL, +}; + +static void most_snd_grp_release(struct config_item *item) +{ + struct most_snd_grp *group = to_most_snd_grp(item); + + list_del(&group->list); + kfree(group); +} + +static struct configfs_item_operations most_snd_grp_item_ops = { + .release = most_snd_grp_release, +}; + +static struct configfs_group_operations most_snd_grp_group_ops = { + .make_item = most_snd_grp_make_item, +}; + +static const struct config_item_type most_snd_grp_type = { + .ct_item_ops = &most_snd_grp_item_ops, + .ct_group_ops = &most_snd_grp_group_ops, + .ct_attrs = most_snd_grp_attrs, + .ct_owner = THIS_MODULE, +}; + +struct most_sound { + struct configfs_subsystem subsys; + struct list_head soundcard_list; +}; + +static struct config_group *most_sound_make_group(struct config_group *group, + const char *name) +{ + struct most_snd_grp *most; + struct most_sound *ms = container_of(to_configfs_subsystem(group), + struct most_sound, subsys); + + list_for_each_entry(most, &ms->soundcard_list, list) { + if (!most->create_card) { + pr_info("adapter configuration still in progress.\n"); + return ERR_PTR(-EPROTO); + } + } + most = kzalloc(sizeof(*most), GFP_KERNEL); + if (!most) + return ERR_PTR(-ENOMEM); + + config_group_init_type_name(&most->group, name, &most_snd_grp_type); + list_add_tail(&most->list, &ms->soundcard_list); + return &most->group; +} + +static struct configfs_group_operations most_sound_group_ops = { + .make_group = most_sound_make_group, +}; + +static const struct config_item_type most_sound_type = { + .ct_group_ops = &most_sound_group_ops, + .ct_owner = THIS_MODULE, +}; + +static struct most_sound most_sound_subsys = { + .subsys = { + .su_group = { + .cg_item = { + .ci_namebuf = "most_sound", + .ci_type = &most_sound_type, + }, + }, + }, +}; + +int most_register_configfs_subsys(struct core_component *c) +{ + int ret; + + if (!strcmp(c->name, "cdev")) + ret = configfs_register_subsystem(&most_cdev_subsys); + else if (!strcmp(c->name, "net")) + ret = configfs_register_subsystem(&most_net_subsys); + else if (!strcmp(c->name, "video")) + ret = configfs_register_subsystem(&most_video_subsys); + else if (!strcmp(c->name, "sound")) + ret = configfs_register_subsystem(&most_sound_subsys.subsys); + else + return -ENODEV; + + if (ret) { + pr_err("Error %d while registering subsystem %s\n", + ret, c->name); + } + return ret; +} +EXPORT_SYMBOL_GPL(most_register_configfs_subsys); + +void most_interface_register_notify(const char *mdev) +{ + bool register_snd_card = false; + struct mdev_link *mdev_link; + + list_for_each_entry(mdev_link, &mdev_link_list, list) { + if (!strcmp(mdev_link->device, mdev)) { + set_config_and_add_link(mdev_link); + if (!strcmp(mdev_link->comp, "sound")) + register_snd_card = true; + } + } + if (register_snd_card) + most_cfg_complete("sound"); +} + +void most_deregister_configfs_subsys(struct core_component *c) +{ + if (!strcmp(c->name, "cdev")) + configfs_unregister_subsystem(&most_cdev_subsys); + else if (!strcmp(c->name, "net")) + configfs_unregister_subsystem(&most_net_subsys); + else if (!strcmp(c->name, "video")) + configfs_unregister_subsystem(&most_video_subsys); + else if (!strcmp(c->name, "sound")) + configfs_unregister_subsystem(&most_sound_subsys.subsys); +} +EXPORT_SYMBOL_GPL(most_deregister_configfs_subsys); + +int __init configfs_init(void) +{ + config_group_init(&most_cdev_subsys.su_group); + mutex_init(&most_cdev_subsys.su_mutex); + + config_group_init(&most_net_subsys.su_group); + mutex_init(&most_net_subsys.su_mutex); + + config_group_init(&most_video_subsys.su_group); + mutex_init(&most_video_subsys.su_mutex); + + config_group_init(&most_sound_subsys.subsys.su_group); + mutex_init(&most_sound_subsys.subsys.su_mutex); + + INIT_LIST_HEAD(&most_sound_subsys.soundcard_list); + INIT_LIST_HEAD(&mdev_link_list); + + return 0; +} diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 956daf8c3bd2..86a8545c8d97 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -272,19 +272,6 @@ static ssize_t set_number_of_buffers_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers); } -static ssize_t set_number_of_buffers_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct most_channel *c = to_channel(dev); - int ret = kstrtou16(buf, 0, &c->cfg.num_buffers); - - if (ret) - return ret; - return count; -} - static ssize_t set_buffer_size_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -294,19 +281,6 @@ static ssize_t set_buffer_size_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size); } -static ssize_t set_buffer_size_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct most_channel *c = to_channel(dev); - int ret = kstrtou16(buf, 0, &c->cfg.buffer_size); - - if (ret) - return ret; - return count; -} - static ssize_t set_direction_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -320,28 +294,6 @@ static ssize_t set_direction_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "unconfigured\n"); } -static ssize_t set_direction_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct most_channel *c = to_channel(dev); - - 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 device *dev, struct device_attribute *attr, char *buf) @@ -356,28 +308,6 @@ static ssize_t set_datatype_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "unconfigured\n"); } -static ssize_t set_datatype_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - int i; - 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)) { - 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 device *dev, struct device_attribute *attr, char *buf) @@ -387,19 +317,6 @@ static ssize_t set_subbuffer_size_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size); } -static ssize_t set_subbuffer_size_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct most_channel *c = to_channel(dev); - int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size); - - if (ret) - return ret; - return count; -} - static ssize_t set_packets_per_xact_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -409,19 +326,6 @@ static ssize_t set_packets_per_xact_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact); } -static ssize_t set_packets_per_xact_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct most_channel *c = to_channel(dev); - int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact); - - if (ret) - return ret; - return count; -} - static ssize_t set_dbr_size_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -430,18 +334,6 @@ static ssize_t set_dbr_size_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.dbr_size); } -static ssize_t set_dbr_size_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct most_channel *c = to_channel(dev); - int ret = kstrtou16(buf, 0, &c->cfg.dbr_size); - - if (ret) - return ret; - return count; -} - #define to_dev_attr(a) container_of(a, struct device_attribute, attr) static umode_t channel_attr_is_visible(struct kobject *kobj, struct attribute *attr, int index) @@ -469,13 +361,13 @@ 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 DEVICE_ATTR_RW(set_dbr_size); +static DEVICE_ATTR_RO(set_buffer_size); +static DEVICE_ATTR_RO(set_number_of_buffers); +static DEVICE_ATTR_RO(set_direction); +static DEVICE_ATTR_RO(set_datatype); +static DEVICE_ATTR_RO(set_subbuffer_size); +static DEVICE_ATTR_RO(set_packets_per_xact); +static DEVICE_ATTR_RO(set_dbr_size); static struct attribute *channel_attrs[] = { DEV_ATTR(available_directions), @@ -701,6 +593,7 @@ static struct most_channel *get_channel(char *mdev, char *mdev_ch) static inline int link_channel_to_component(struct most_channel *c, struct core_component *comp, + char *name, char *comp_param) { int ret; @@ -714,7 +607,8 @@ inline int link_channel_to_component(struct most_channel *c, return -ENOSPC; *comp_ptr = comp; - ret = comp->probe_channel(c->iface, c->channel_id, &c->cfg, comp_param); + ret = comp->probe_channel(c->iface, c->channel_id, &c->cfg, name, + comp_param); if (ret) { *comp_ptr = NULL; return ret; @@ -722,65 +616,118 @@ inline int link_channel_to_component(struct most_channel *c, return 0; } -/** - * 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 - * 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 (device, channel) pair and probes the component - * - * Example: - * (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 - */ -static ssize_t add_link_store(struct device_driver *drv, - const char *buf, - size_t len) +int most_set_cfg_buffer_size(char *mdev, char *mdev_ch, u16 val) { - struct most_channel *c; - struct core_component *comp; - char buffer[STRING_SIZE]; - char *mdev; - char *mdev_ch; - 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); + struct most_channel *c = get_channel(mdev, mdev_ch); - strlcpy(buffer, buf, max_len); - ret = split_string(buffer, &mdev, &mdev_ch, &comp_name, &comp_param); - if (ret) - return ret; - comp = match_component(comp_name); - if (!comp) + if (!c) return -ENODEV; - if (!comp_param || *comp_param == 0) { - snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev, - mdev_ch); - comp_param = devnod_buf; + c->cfg.buffer_size = val; + return 0; +} + +int most_set_cfg_subbuffer_size(char *mdev, char *mdev_ch, u16 val) +{ + struct most_channel *c = get_channel(mdev, mdev_ch); + + if (!c) + return -ENODEV; + c->cfg.subbuffer_size = val; + return 0; +} + +int most_set_cfg_dbr_size(char *mdev, char *mdev_ch, u16 val) +{ + struct most_channel *c = get_channel(mdev, mdev_ch); + + if (!c) + return -ENODEV; + c->cfg.dbr_size = val; + return 0; +} + +int most_set_cfg_num_buffers(char *mdev, char *mdev_ch, u16 val) +{ + struct most_channel *c = get_channel(mdev, mdev_ch); + + if (!c) + return -ENODEV; + c->cfg.num_buffers = val; + return 0; +} + +int most_set_cfg_datatype(char *mdev, char *mdev_ch, char *buf) +{ + int i; + struct most_channel *c = get_channel(mdev, mdev_ch); + + if (!c) + return -ENODEV; + 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; + } } - c = get_channel(mdev, mdev_ch); + if (i == ARRAY_SIZE(ch_data_type)) + pr_info("WARN: invalid attribute settings\n"); + return 0; +} + +int most_set_cfg_direction(char *mdev, char *mdev_ch, char *buf) +{ + struct most_channel *c = get_channel(mdev, mdev_ch); + + if (!c) + return -ENODEV; + 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("Invalid direction\n"); + return -ENODATA; + } + return 0; +} + +int most_set_cfg_packets_xact(char *mdev, char *mdev_ch, u16 val) +{ + struct most_channel *c = get_channel(mdev, mdev_ch); + if (!c) return -ENODEV; + c->cfg.packets_per_xact = val; + return 0; +} + +int most_cfg_complete(char *comp_name) +{ + struct core_component *comp; + + comp = match_component(comp_name); + if (!comp) + return -ENODEV; - ret = link_channel_to_component(c, comp, comp_param); - if (ret) - return ret; - return len; + return comp->cfg_complete(); } +int most_add_link(char *mdev, char *mdev_ch, char *comp_name, char *link_name, + char *comp_param) +{ + struct most_channel *c = get_channel(mdev, mdev_ch); + struct core_component *comp = match_component(comp_name); + + if (!c || !comp) + return -ENODEV; + + return link_channel_to_component(c, comp, link_name, comp_param); +} /** * remove_link_store - store function for remove_link attribute * @drv: device driver @@ -823,17 +770,36 @@ static ssize_t remove_link_store(struct device_driver *drv, return len; } +int most_remove_link(char *mdev, char *mdev_ch, char *comp_name) +{ + struct most_channel *c; + struct core_component *comp; + + comp = match_component(comp_name); + if (!comp) + return -ENODEV; + c = get_channel(mdev, mdev_ch); + if (!c) + return -ENODEV; + + if (comp->disconnect_channel(c->iface, c->channel_id)) + return -EIO; + if (c->pipe0.comp == comp) + c->pipe0.comp = NULL; + if (c->pipe1.comp == comp) + c->pipe1.comp = NULL; + return 0; +} + #define DRV_ATTR(_name) (&driver_attr_##_name.attr) static DRIVER_ATTR_RO(links); static DRIVER_ATTR_RO(components); -static DRIVER_ATTR_WO(add_link); static DRIVER_ATTR_WO(remove_link); static struct attribute *mc_attrs[] = { DRV_ATTR(links), DRV_ATTR(components), - DRV_ATTR(add_link), DRV_ATTR(remove_link), NULL, }; @@ -1431,7 +1397,7 @@ int most_register_interface(struct most_interface *iface) INIT_LIST_HEAD(&iface->p->channel_list); iface->p->dev_id = id; - strcpy(iface->p->name, iface->description); + strscpy(iface->p->name, iface->description, sizeof(iface->p->name)); iface->dev.init_name = iface->p->name; iface->dev.bus = &mc.bus; iface->dev.parent = &mc.dev; @@ -1487,6 +1453,7 @@ int most_register_interface(struct most_interface *iface) } pr_info("registered new device mdev%d (%s)\n", id, iface->description); + most_interface_register_notify(iface->description); return 0; err_free_most_channel: @@ -1621,7 +1588,7 @@ static int __init most_init(void) err = -ENOMEM; goto err_unregister_driver; } - + configfs_init(); return 0; err_unregister_driver: diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h index 64cc02f161e7..652aaa771029 100644 --- a/drivers/staging/most/core.h +++ b/drivers/staging/most/core.h @@ -266,11 +266,13 @@ struct core_component { struct list_head list; const char *name; int (*probe_channel)(struct most_interface *iface, int channel_idx, - struct most_channel_config *cfg, char *name); + struct most_channel_config *cfg, char *name, + char *param); 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); + int (*cfg_complete)(void); }; /** @@ -318,5 +320,19 @@ int most_start_channel(struct most_interface *iface, int channel_idx, struct core_component *comp); int most_stop_channel(struct most_interface *iface, int channel_idx, struct core_component *comp); - +int __init configfs_init(void); +int most_register_configfs_subsys(struct core_component *comp); +void most_deregister_configfs_subsys(struct core_component *comp); +int most_add_link(char *mdev, char *mdev_ch, char *comp_name, char *link_name, + char *comp_param); +int most_remove_link(char *mdev, char *mdev_ch, char *comp_name); +int most_set_cfg_buffer_size(char *mdev, char *mdev_ch, u16 val); +int most_set_cfg_subbuffer_size(char *mdev, char *mdev_ch, u16 val); +int most_set_cfg_dbr_size(char *mdev, char *mdev_ch, u16 val); +int most_set_cfg_num_buffers(char *mdev, char *mdev_ch, u16 val); +int most_set_cfg_datatype(char *mdev, char *mdev_ch, char *buf); +int most_set_cfg_direction(char *mdev, char *mdev_ch, char *buf); +int most_set_cfg_packets_xact(char *mdev, char *mdev_ch, u16 val); +int most_cfg_complete(char *comp_name); +void most_interface_register_notify(const char *mdev_name); #endif /* MOST_CORE_H_ */ diff --git a/drivers/staging/most/dim2/Kconfig b/drivers/staging/most/dim2/Kconfig index 5aeef22c3cba..22f6900187b5 100644 --- a/drivers/staging/most/dim2/Kconfig +++ b/drivers/staging/most/dim2/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # MediaLB configuration # diff --git a/drivers/staging/most/dim2/Makefile b/drivers/staging/most/dim2/Makefile index 6d15f045a767..116f04d69244 100644 --- a/drivers/staging/most/dim2/Makefile +++ b/drivers/staging/most/dim2/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MOST_DIM2) += most_dim2.o most_dim2-objs := dim2.o hal.o sysfs.o diff --git a/drivers/staging/most/dim2/errors.h b/drivers/staging/most/dim2/errors.h index 3487510fbd2f..268332e5735e 100644 --- a/drivers/staging/most/dim2/errors.h +++ b/drivers/staging/most/dim2/errors.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * errors.h - Definitions of errors for DIM2 HAL API * (MediaLB, Device Interface Macro IP, OS62420) diff --git a/drivers/staging/most/dim2/hal.h b/drivers/staging/most/dim2/hal.h index e04a5350f134..fca6c22de8a6 100644 --- a/drivers/staging/most/dim2/hal.h +++ b/drivers/staging/most/dim2/hal.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * hal.h - DIM2 HAL interface * (MediaLB, Device Interface Macro IP, OS62420) diff --git a/drivers/staging/most/dim2/reg.h b/drivers/staging/most/dim2/reg.h index 4343a483017e..b0f36c208a57 100644 --- a/drivers/staging/most/dim2/reg.h +++ b/drivers/staging/most/dim2/reg.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * reg.h - Definitions for registers of DIM2 * (MediaLB, Device Interface Macro IP, OS62420) diff --git a/drivers/staging/most/dim2/sysfs.h b/drivers/staging/most/dim2/sysfs.h index 33756a3bffe2..24277a17cff3 100644 --- a/drivers/staging/most/dim2/sysfs.h +++ b/drivers/staging/most/dim2/sysfs.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * sysfs.h - MediaLB sysfs information * diff --git a/drivers/staging/most/i2c/Kconfig b/drivers/staging/most/i2c/Kconfig index 79d0ff27f56d..19a094b5bee0 100644 --- a/drivers/staging/most/i2c/Kconfig +++ b/drivers/staging/most/i2c/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # MOST I2C configuration # @@ -5,7 +6,7 @@ config MOST_I2C tristate "I2C" depends on I2C - ---help--- + 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 diff --git a/drivers/staging/most/i2c/Makefile b/drivers/staging/most/i2c/Makefile index c032fea979b3..2b3769dc19e7 100644 --- a/drivers/staging/most/i2c/Makefile +++ b/drivers/staging/most/i2c/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MOST_I2C) += most_i2c.o most_i2c-objs := i2c.o diff --git a/drivers/staging/most/net/Kconfig b/drivers/staging/most/net/Kconfig index 795330ba94ef..ed8ac7e076d1 100644 --- a/drivers/staging/most/net/Kconfig +++ b/drivers/staging/most/net/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # MOST Networking configuration # @@ -6,7 +7,7 @@ config MOST_NET tristate "Net" depends on NET - ---help--- + help Say Y here if you want to commumicate via a networking device. To compile this driver as a module, choose M here: the diff --git a/drivers/staging/most/net/Makefile b/drivers/staging/most/net/Makefile index 820faec6b296..f0ac64dee71b 100644 --- a/drivers/staging/most/net/Makefile +++ b/drivers/staging/most/net/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MOST_NET) += most_net.o most_net-objs := net.o diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index e20584b1b112..c8a64e209027 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -293,7 +293,8 @@ static struct net_dev_context *get_net_dev_hold(struct most_interface *iface) } static int comp_probe_channel(struct most_interface *iface, int channel_idx, - struct most_channel_config *ccfg, char *name) + struct most_channel_config *ccfg, char *name, + char *args) { struct net_dev_context *nd; struct net_dev_channel *ch; diff --git a/drivers/staging/most/sound/Kconfig b/drivers/staging/most/sound/Kconfig index 115262a58a42..ad9f7821af7d 100644 --- a/drivers/staging/most/sound/Kconfig +++ b/drivers/staging/most/sound/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # MOST ALSA configuration # @@ -6,7 +7,7 @@ config MOST_SOUND tristate "Sound" depends on SND select SND_PCM - ---help--- + help Say Y here if you want to commumicate via ALSA/sound devices. To compile this driver as a module, choose M here: the diff --git a/drivers/staging/most/sound/Makefile b/drivers/staging/most/sound/Makefile index 5bb55bb108fb..a3d086c6ca70 100644 --- a/drivers/staging/most/sound/Makefile +++ b/drivers/staging/most/sound/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MOST_SOUND) += most_sound.o most_sound-objs := sound.o diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 79ab3a78c5ec..342f390d68b3 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -20,6 +20,7 @@ #include <most/core.h> #define DRIVER_NAME "sound" +#define STRING_SIZE 80 static struct core_component comp; @@ -471,17 +472,11 @@ static const struct snd_pcm_ops pcm_ops = { .page = snd_pcm_lib_get_vmalloc_page, }; -static int split_arg_list(char *buf, char **device_name, u16 *ch_num, - char **sample_res, u8 *create) +static int split_arg_list(char *buf, u16 *ch_num, char **sample_res) { char *num; int ret; - *device_name = strsep(&buf, "."); - if (!*device_name) { - pr_err("Missing sound card name\n"); - return -EIO; - } num = strsep(&buf, "x"); if (!num) goto err; @@ -492,8 +487,6 @@ static int split_arg_list(char *buf, char **device_name, u16 *ch_num, if (!*sample_res) goto err; - if (buf && !strcmp(buf, "create")) - *create = 1; return 0; err: @@ -579,7 +572,7 @@ static void release_adapter(struct sound_adapter *adpt) */ static int audio_probe_channel(struct most_interface *iface, int channel_id, struct most_channel_config *cfg, - char *arg_list) + char *device_name, char *arg_list) { struct channel *channel; struct sound_adapter *adpt; @@ -588,10 +581,9 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id, int capture_count = 0; int ret; int direction; - char *device_name; u16 ch_num; - u8 create = 0; char *sample_res; + char arg_list_cpy[STRING_SIZE]; if (!iface) return -EINVAL; @@ -600,9 +592,8 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id, pr_err("Incompatible channel type\n"); return -EINVAL; } - - ret = split_arg_list(arg_list, &device_name, &ch_num, &sample_res, - &create); + strlcpy(arg_list_cpy, arg_list, STRING_SIZE); + ret = split_arg_list(arg_list_cpy, &ch_num, &sample_res); if (ret < 0) return ret; @@ -622,7 +613,7 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id, INIT_LIST_HEAD(&adpt->dev_list); iface->priv = adpt; list_add_tail(&adpt->list, &adpt_list); - ret = snd_card_new(&iface->dev, -1, "INIC", THIS_MODULE, + ret = snd_card_new(iface->driver_dev, -1, "INIC", THIS_MODULE, sizeof(*channel), &adpt->card); if (ret < 0) goto err_free_adpt; @@ -673,12 +664,6 @@ skip_adpt_alloc: strscpy(pcm->name, device_name, sizeof(pcm->name)); snd_pcm_set_ops(pcm, direction, &pcm_ops); - if (create) { - ret = snd_card_register(adpt->card); - if (ret < 0) - goto err_free_adpt; - adpt->registered = true; - } return 0; err_free_adpt: @@ -686,6 +671,26 @@ err_free_adpt: return ret; } +static int audio_create_sound_card(void) +{ + int ret; + struct sound_adapter *adpt; + + list_for_each_entry(adpt, &adpt_list, list) { + if (!adpt->registered) + goto adpt_alloc; + } + return -ENODEV; +adpt_alloc: + ret = snd_card_register(adpt->card); + if (ret < 0) { + release_adapter(adpt); + return ret; + } + adpt->registered = true; + return 0; +} + /** * audio_disconnect_channel - function to disconnect a channel * @iface: pointer to interface instance @@ -782,20 +787,30 @@ static struct core_component comp = { .disconnect_channel = audio_disconnect_channel, .rx_completion = audio_rx_completion, .tx_completion = audio_tx_completion, + .cfg_complete = audio_create_sound_card, }; static int __init audio_init(void) { + int ret; + pr_info("init()\n"); INIT_LIST_HEAD(&adpt_list); - return most_register_component(&comp); + ret = most_register_component(&comp); + if (ret) + pr_err("Failed to register %s\n", comp.name); + ret = most_register_configfs_subsys(&comp); + if (ret) + pr_err("Failed to register %s configfs subsys\n", comp.name); + return ret; } static void __exit audio_exit(void) { pr_info("exit()\n"); + most_deregister_configfs_subsys(&comp); most_deregister_component(&comp); } diff --git a/drivers/staging/most/usb/Kconfig b/drivers/staging/most/usb/Kconfig index ebbdb573a9a6..a86f1f63def4 100644 --- a/drivers/staging/most/usb/Kconfig +++ b/drivers/staging/most/usb/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # MOST USB configuration # @@ -5,7 +6,7 @@ config MOST_USB tristate "USB" depends on USB && NET - ---help--- + help Say Y here if you want to connect via USB to network tranceiver. This device driver depends on the networking AIM. diff --git a/drivers/staging/most/usb/Makefile b/drivers/staging/most/usb/Makefile index 910cd08bad7c..83cf2ead7122 100644 --- a/drivers/staging/most/usb/Makefile +++ b/drivers/staging/most/usb/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MOST_USB) += most_usb.o most_usb-objs := usb.o diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c index c0293d8d5934..360cb5b7a10b 100644 --- a/drivers/staging/most/usb/usb.c +++ b/drivers/staging/most/usb/usb.c @@ -1072,7 +1072,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) mdev->iface.num_channels = num_endpoints; snprintf(mdev->description, sizeof(mdev->description), - "usb_device %d-%s:%d.%d", + "%d-%s:%d.%d", usb_dev->bus->busnum, usb_dev->devpath, usb_dev->config->desc.bConfigurationValue, diff --git a/drivers/staging/most/video/Kconfig b/drivers/staging/most/video/Kconfig index ce6af4f951a6..e0964ca5e7b3 100644 --- a/drivers/staging/most/video/Kconfig +++ b/drivers/staging/most/video/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # MOST V4L2 configuration # @@ -5,7 +6,7 @@ config MOST_VIDEO tristate "Video" depends on VIDEO_V4L2 - ---help--- + help Say Y here if you want to commumicate via Video 4 Linux. To compile this driver as a module, choose M here: the diff --git a/drivers/staging/most/video/Makefile b/drivers/staging/most/video/Makefile index c6e01b6ecfe6..2d857d3cbcc8 100644 --- a/drivers/staging/most/video/Makefile +++ b/drivers/staging/most/video/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MOST_VIDEO) += most_video.o most_video-objs := video.o diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index ad7e28ab9a4f..adca250062e1 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -453,7 +453,8 @@ static void comp_v4l2_dev_release(struct v4l2_device *v4l2_dev) } static int comp_probe_channel(struct most_interface *iface, int channel_idx, - struct most_channel_config *ccfg, char *name) + struct most_channel_config *ccfg, char *name, + char *args) { int ret; struct most_video_dev *mdev = get_comp_dev(iface, channel_idx); |