aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/most
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/most')
-rw-r--r--drivers/staging/most/Documentation/ABI/sysfs-class-most.txt2
-rw-r--r--drivers/staging/most/aim-cdev/cdev.c68
-rw-r--r--drivers/staging/most/aim-network/networking.c53
-rw-r--r--drivers/staging/most/aim-sound/sound.c114
-rw-r--r--drivers/staging/most/aim-v4l2/Makefile1
-rw-r--r--drivers/staging/most/aim-v4l2/video.c50
-rw-r--r--drivers/staging/most/hdm-dim2/Kconfig2
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_hal.c62
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_hal.h5
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_hdm.c79
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_hdm.h3
-rw-r--r--drivers/staging/most/hdm-dim2/dim2_sysfs.c3
-rw-r--r--drivers/staging/most/hdm-i2c/hdm_i2c.c45
-rw-r--r--drivers/staging/most/hdm-usb/hdm_usb.c162
-rw-r--r--drivers/staging/most/mostcore/core.c230
-rw-r--r--drivers/staging/most/mostcore/mostcore.h13
16 files changed, 438 insertions, 454 deletions
diff --git a/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt b/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt
index 380c137089d0..42ff0d8b2ead 100644
--- a/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt
+++ b/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt
@@ -47,7 +47,7 @@ Date: June 2015
KernelVersion: 4.3
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
- Indicates the type of peripherial interface the current device
+ Indicates the type of peripheral interface the current device
uses.
Users:
diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c
index 0a13d8d0fa39..dc3fb25b52aa 100644
--- a/drivers/staging/most/aim-cdev/cdev.c
+++ b/drivers/staging/most/aim-cdev/cdev.c
@@ -18,6 +18,7 @@
#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>
@@ -27,6 +28,7 @@ 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;
@@ -44,11 +46,11 @@ struct aim_channel {
atomic_t 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 struct aim_channel *get_channel(struct most_interface *iface, int id)
{
struct aim_channel *channel, *tmp;
@@ -85,8 +87,8 @@ static int aim_open(struct inode *inode, struct file *filp)
filp->private_data = channel;
if (((channel->cfg->direction == MOST_CH_RX) &&
- ((filp->f_flags & O_ACCMODE) != O_RDONLY))
- || ((channel->cfg->direction == MOST_CH_TX) &&
+ ((filp->f_flags & O_ACCMODE) != O_RDONLY)) ||
+ ((channel->cfg->direction == MOST_CH_TX) &&
((filp->f_flags & O_ACCMODE) != O_WRONLY))) {
pr_info("WARN: Access flags mismatch\n");
return -EACCES;
@@ -97,7 +99,8 @@ static int aim_open(struct inode *inode, struct file *filp)
return -EBUSY;
}
- ret = most_start_channel(channel->iface, channel->channel_id);
+ ret = most_start_channel(channel->iface, channel->channel_id,
+ &cdev_aim);
if (ret)
atomic_dec(&channel->access_ref);
return ret;
@@ -131,11 +134,11 @@ static int aim_close(struct inode *inode, struct file *filp)
}
mutex_unlock(&channel->io_mutex);
- while (0 != kfifo_out((struct kfifo *)&channel->fifo, &mbo, 1))
+ while (kfifo_out((struct kfifo *)&channel->fifo, &mbo, 1))
most_put_mbo(mbo);
- if (channel->keep_mbo == true)
+ if (channel->keep_mbo)
most_put_mbo(channel->stacked_mbo);
- ret = most_stop_channel(channel->iface, channel->channel_id);
+ ret = most_stop_channel(channel->iface, channel->channel_id, &cdev_aim);
atomic_dec(&channel->access_ref);
wake_up_interruptible(&channel->wq);
return ret;
@@ -165,16 +168,17 @@ static ssize_t aim_write(struct file *filp, const char __user *buf,
}
mutex_unlock(&channel->io_mutex);
- mbo = most_get_mbo(channel->iface, channel->channel_id);
+ mbo = most_get_mbo(channel->iface, channel->channel_id, &cdev_aim);
- if (!mbo && channel->dev) {
+ if (!mbo) {
if ((filp->f_flags & O_NONBLOCK))
return -EAGAIN;
if (wait_event_interruptible(
channel->wq,
(mbo = most_get_mbo(channel->iface,
- channel->channel_id)) ||
- (channel->dev == NULL)))
+ channel->channel_id,
+ &cdev_aim)) ||
+ (!channel->dev)))
return -ERESTARTSYS;
}
@@ -204,8 +208,7 @@ static ssize_t aim_write(struct file *filp, const char __user *buf,
}
return actual_len - retval;
error:
- if (mbo)
- most_put_mbo(mbo);
+ most_put_mbo(mbo);
return err;
}
@@ -224,18 +227,17 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
struct mbo *mbo;
struct aim_channel *channel = filp->private_data;
- if (channel->keep_mbo == true) {
+ if (channel->keep_mbo) {
mbo = channel->stacked_mbo;
channel->keep_mbo = false;
goto start_copy;
}
- while ((0 == kfifo_out(&channel->fifo, &mbo, 1))
- && (channel->dev != NULL)) {
+ while ((!kfifo_out(&channel->fifo, &mbo, 1)) && (channel->dev)) {
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
if (wait_event_interruptible(channel->wq,
(!kfifo_is_empty(&channel->fifo) ||
- (channel->dev == NULL))))
+ (!channel->dev))))
return -ERESTARTSYS;
}
@@ -259,7 +261,7 @@ start_copy:
retval = not_copied ? proc_len - not_copied : proc_len;
- if (channel->keep_mbo == true) {
+ if (channel->keep_mbo) {
channel->mbo_offs = retval;
channel->stacked_mbo = mbo;
} else {
@@ -270,6 +272,28 @@ start_copy:
return retval;
}
+static inline bool __must_check IS_ERR_OR_FALSE(int x)
+{
+ return x <= 0;
+}
+
+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 (!IS_ERR_OR_FALSE(channel_has_mbo(c->iface, c->channel_id)))
+ mask |= POLLOUT | POLLWRNORM;
+ }
+ return mask;
+}
+
/**
* Initialization of struct file_operations
*/
@@ -279,6 +303,7 @@ static const struct file_operations channel_fops = {
.write = aim_write,
.open = aim_open,
.release = aim_close,
+ .poll = aim_poll,
};
/**
@@ -300,7 +325,7 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id)
}
channel = get_channel(iface, channel_id);
- if (channel == NULL)
+ if (!channel)
return -ENXIO;
mutex_lock(&channel->io_mutex);
@@ -337,7 +362,7 @@ static int aim_rx_completion(struct mbo *mbo)
return -EINVAL;
channel = get_channel(mbo->ifp, mbo->hdm_channel_id);
- if (channel == NULL)
+ if (!channel)
return -ENXIO;
kfifo_in(&channel->fifo, &mbo, 1);
@@ -370,7 +395,7 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id)
}
channel = get_channel(iface, channel_id);
- if (channel == NULL)
+ if (!channel)
return -ENXIO;
wake_up_interruptible(&channel->wq);
return 0;
@@ -413,7 +438,6 @@ static int aim_probe(struct most_interface *iface, int channel_id,
channel = kzalloc(sizeof(*channel), GFP_KERNEL);
if (!channel) {
- pr_info("failed to alloc channel object\n");
retval = -ENOMEM;
goto error_alloc_channel;
}
diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
index c8ab2399faad..3c7beb03871d 100644
--- a/drivers/staging/most/aim-network/networking.c
+++ b/drivers/staging/most/aim-network/networking.c
@@ -24,7 +24,6 @@
#include "mostcore.h"
#include "networking.h"
-
#define MEP_HDR_LEN 8
#define MDP_HDR_LEN 16
#define MAMAC_DATA_LEN (1024 - MDP_HDR_LEN)
@@ -47,8 +46,6 @@
#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)
@@ -81,7 +78,6 @@ static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
static struct spinlock list_lock;
static struct most_aim aim;
-
static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
{
u8 *buff = mbo->virt_address;
@@ -186,7 +182,7 @@ static int most_nd_open(struct net_device *dev)
{
struct net_dev_context *nd = dev->ml_priv;
- pr_info("open net device %s\n", dev->name);
+ netdev_info(dev, "open net device\n");
BUG_ON(nd->dev != dev);
@@ -195,14 +191,14 @@ static int most_nd_open(struct net_device *dev)
BUG_ON(!nd->tx.linked || !nd->rx.linked);
- if (most_start_channel(nd->iface, nd->rx.ch_id)) {
- pr_err("most_start_channel() failed\n");
+ if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) {
+ netdev_err(dev, "most_start_channel() failed\n");
return -EBUSY;
}
- if (most_start_channel(nd->iface, nd->tx.ch_id)) {
- pr_err("most_start_channel() failed\n");
- most_stop_channel(nd->iface, nd->rx.ch_id);
+ 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);
return -EBUSY;
}
@@ -222,14 +218,14 @@ static int most_nd_stop(struct net_device *dev)
{
struct net_dev_context *nd = dev->ml_priv;
- pr_info("stop net device %s\n", dev->name);
+ netdev_info(dev, "stop net device\n");
BUG_ON(nd->dev != dev);
netif_stop_queue(dev);
if (nd->channels_opened) {
- most_stop_channel(nd->iface, nd->rx.ch_id);
- most_stop_channel(nd->iface, nd->tx.ch_id);
+ most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
+ most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
nd->channels_opened = false;
}
@@ -245,7 +241,7 @@ static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb,
BUG_ON(nd->dev != dev);
- mbo = most_get_mbo(nd->iface, nd->tx.ch_id);
+ mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim);
if (!mbo) {
netif_stop_queue(dev);
@@ -281,7 +277,7 @@ static const struct net_device_ops most_nd_ops = {
static void most_nd_setup(struct net_device *dev)
{
- pr_info("setup net device %s\n", dev->name);
+ netdev_info(dev, "setup net device\n");
ether_setup(dev);
dev->netdev_ops = &most_nd_ops;
}
@@ -295,7 +291,7 @@ static void most_net_rm_netdev_safe(struct net_dev_context *nd)
unregister_netdev(nd->dev);
free_netdev(nd->dev);
- nd->dev = 0;
+ nd->dev = NULL;
}
static struct net_dev_context *get_net_dev_context(
@@ -349,7 +345,8 @@ 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", NET_NAME_UNKNOWN,
+ most_nd_setup);
if (!dev) {
pr_err("no memory for net_device\n");
@@ -357,10 +354,13 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
}
nd->dev = dev;
+ ch->ch_id = channel_idx;
+ ch->linked = true;
dev->ml_priv = nd;
if (register_netdev(dev)) {
pr_err("registering net device failed\n");
+ ch->linked = false;
free_netdev(dev);
return -EINVAL;
}
@@ -428,7 +428,7 @@ static int aim_rx_data(struct mbo *mbo)
const u32 zero = 0;
struct net_dev_context *nd;
char *buf = mbo->virt_address;
- uint32_t len = mbo->processed_length;
+ u32 len = mbo->processed_length;
struct sk_buff *skb;
struct net_device *dev;
@@ -464,7 +464,7 @@ static int aim_rx_data(struct mbo *mbo)
if (nd->is_mamac) {
/* dest */
- memcpy(skb_put(skb, ETH_ALEN), dev->dev_addr, ETH_ALEN);
+ ether_addr_copy(skb_put(skb, ETH_ALEN), dev->dev_addr);
/* src */
memcpy(skb_put(skb, 4), &zero, 4);
@@ -491,15 +491,18 @@ out:
return 0;
}
+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)
{
pr_info("most_net_init()\n");
spin_lock_init(&list_lock);
- aim.name = "networking";
- aim.probe_channel = aim_probe_channel;
- aim.disconnect_channel = aim_disconnect_channel;
- aim.tx_completion = aim_resume_tx_channel;
- aim.rx_completion = aim_rx_data;
return most_register_aim(&aim);
}
@@ -548,7 +551,7 @@ void most_deliver_netinfo(struct most_interface *iface,
return;
if (mac_addr)
- memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
+ ether_addr_copy(dev->dev_addr, mac_addr);
if (nd->link_stat != link_stat) {
nd->link_stat = link_stat;
diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c
index 860302eebda7..9c645801cff4 100644
--- a/drivers/staging/most/aim-sound/sound.c
+++ b/drivers/staging/most/aim-sound/sound.c
@@ -19,6 +19,7 @@
#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>
@@ -26,6 +27,7 @@
#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
@@ -44,6 +46,7 @@ static struct list_head dev_list;
*/
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;
@@ -65,18 +68,6 @@ struct channel {
SNDRV_PCM_INFO_INTERLEAVED | \
SNDRV_PCM_INFO_BLOCK_TRANSFER)
-/**
- * Initialization of struct snd_pcm_hardware
- */
-static struct snd_pcm_hardware pcm_hardware_template = {
- .info = MOST_PCM_INFO,
- .rates = SNDRV_PCM_RATE_48000,
- .rate_min = 48000,
- .rate_max = 48000,
- .channels_min = 1,
- .channels_max = 8,
-};
-
#define swap16(val) ( \
(((u16)(val) << 8) & (u16)0xFF00) | \
(((u16)(val) >> 8) & (u16)0x00FF))
@@ -240,8 +231,6 @@ static int playback_thread(void *data)
{
struct channel *const channel = data;
- pr_info("playback thread started\n");
-
while (!kthread_should_stop()) {
struct mbo *mbo = NULL;
bool period_elapsed = false;
@@ -250,8 +239,9 @@ static int playback_thread(void *data)
wait_event_interruptible(
channel->playback_waitq,
kthread_should_stop() ||
- (mbo = most_get_mbo(channel->iface, channel->id)));
-
+ (channel->is_stream_running &&
+ (mbo = most_get_mbo(channel->iface, channel->id,
+ &audio_aim))));
if (!mbo)
continue;
@@ -286,32 +276,25 @@ static int pcm_open(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct most_channel_config *cfg = channel->cfg;
- pr_info("pcm_open(), %s\n", substream->name);
-
channel->substream = substream;
if (cfg->direction == MOST_CH_TX) {
- init_waitqueue_head(&channel->playback_waitq);
- channel->playback_task = kthread_run(&playback_thread, channel,
+ channel->playback_task = kthread_run(playback_thread, channel,
"most_audio_playback");
- if (IS_ERR(channel->playback_task))
+ 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)) {
+ 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 = pcm_hardware_template;
- runtime->hw.buffer_bytes_max = cfg->num_buffers * cfg->buffer_size;
- runtime->hw.period_bytes_min = cfg->buffer_size;
- runtime->hw.period_bytes_max = cfg->buffer_size;
- runtime->hw.periods_min = 1;
- runtime->hw.periods_max = cfg->num_buffers;
-
+ runtime->hw = channel->pcm_hardware;
return 0;
}
@@ -329,11 +312,9 @@ static int pcm_close(struct snd_pcm_substream *substream)
{
struct channel *channel = substream->private_data;
- pr_info("pcm_close(), %s\n", substream->name);
-
if (channel->cfg->direction == MOST_CH_TX)
kthread_stop(channel->playback_task);
- most_stop_channel(channel->iface, channel->id);
+ most_stop_channel(channel->iface, channel->id, &audio_aim);
return 0;
}
@@ -353,8 +334,13 @@ static int pcm_close(struct snd_pcm_substream *substream)
static int pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
- pr_info("pcm_hw_params()\n");
+ 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));
}
@@ -370,8 +356,6 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
*/
static int pcm_hw_free(struct snd_pcm_substream *substream)
{
- pr_info("pcm_hw_free()\n");
-
return snd_pcm_lib_free_vmalloc_buffer(substream);
}
@@ -441,6 +425,7 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd)
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:
@@ -485,8 +470,7 @@ static struct snd_pcm_ops pcm_ops = {
.mmap = snd_pcm_lib_mmap_vmalloc,
};
-
-int split_arg_list(char *buf, char **card_name, char **pcm_format)
+static int split_arg_list(char *buf, char **card_name, char **pcm_format)
{
*card_name = strsep(&buf, ".");
if (!*card_name)
@@ -497,31 +481,59 @@ int split_arg_list(char *buf, char **card_name, char **pcm_format)
return 0;
}
-int audio_set_pcm_format(char *pcm_format, struct most_channel_config *cfg)
+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_hardware_template.formats = SNDRV_PCM_FMTBIT_S8;
+ 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_hardware_template.formats = SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S16_BE;
+ 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_hardware_template.formats = SNDRV_PCM_FMTBIT_S24_3LE |
- SNDRV_PCM_FMTBIT_S24_3BE;
+ 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_hardware_template.formats = SNDRV_PCM_FMTBIT_S32_LE |
- SNDRV_PCM_FMTBIT_S32_BE;
+ 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;
@@ -559,8 +571,6 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id,
char *card_name;
char *pcm_format;
- pr_info("sound_probe_channel()\n");
-
if (!iface)
return -EINVAL;
@@ -588,8 +598,6 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id,
pr_info("PCM format missing\n");
return ret;
}
- if (audio_set_pcm_format(pcm_format, cfg))
- return ret;
ret = snd_card_new(NULL, -1, card_name, THIS_MODULE,
sizeof(*channel), &card);
@@ -601,9 +609,13 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id,
channel->cfg = cfg;
channel->iface = iface;
channel->id = channel_id;
+ init_waitqueue_head(&channel->playback_waitq);
+
+ if (audio_set_hw_params(&channel->pcm_hardware, pcm_format, cfg))
+ goto err_free_card;
snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME);
- snprintf(card->shortname, sizeof(card->shortname), "MOST:%d",
+ 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);
@@ -644,8 +656,6 @@ static int audio_disconnect_channel(struct most_interface *iface,
{
struct channel *channel;
- pr_info("sound_disconnect_channel()\n");
-
channel = get_channel(iface, channel_id);
if (!channel) {
pr_err("sound_disconnect_channel(), invalid channel %d\n",
diff --git a/drivers/staging/most/aim-v4l2/Makefile b/drivers/staging/most/aim-v4l2/Makefile
index 28aa948d6609..69a7524b466c 100644
--- a/drivers/staging/most/aim-v4l2/Makefile
+++ b/drivers/staging/most/aim-v4l2/Makefile
@@ -3,4 +3,3 @@ obj-$(CONFIG_AIM_V4L2) += aim_v4l2.o
aim_v4l2-objs := video.o
ccflags-y += -Idrivers/staging/most/mostcore/
-ccflags-y += -Idrivers/media/video
diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c
index d9687910e4a4..13abf7c275a4 100644
--- a/drivers/staging/most/aim-v4l2/video.c
+++ b/drivers/staging/most/aim-v4l2/video.c
@@ -29,9 +29,9 @@
#include "mostcore.h"
-
#define V4L2_AIM_MAX_INPUT 1
+static struct most_aim aim_info;
struct most_video_dev {
struct most_interface *iface;
@@ -59,11 +59,8 @@ struct aim_fh {
u32 offs;
};
-
static struct list_head video_devices = LIST_HEAD_INIT(video_devices);
static struct spinlock list_lock;
-static struct most_aim aim_info;
-
static inline bool data_ready(struct most_video_dev *mdev)
{
@@ -75,7 +72,6 @@ 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;
@@ -92,7 +88,7 @@ static int aim_vdev_open(struct file *filp)
return -EINVAL;
}
- fh = kzalloc(sizeof(struct aim_fh), GFP_KERNEL);
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
if (!fh)
return -ENOMEM;
@@ -108,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);
+ ret = most_start_channel(mdev->iface, mdev->ch_idx, &aim_info);
if (ret) {
pr_err("most_start_channel() failed\n");
goto err_rm;
@@ -152,7 +148,7 @@ static int aim_vdev_close(struct file *filp)
spin_lock(&mdev->list_lock);
}
spin_unlock(&mdev->list_lock);
- most_stop_channel(mdev->iface, mdev->ch_idx);
+ most_stop_channel(mdev->iface, mdev->ch_idx, &aim_info);
mdev->mute = false;
v4l2_fh_del(&fh->fh);
@@ -243,28 +239,6 @@ static void aim_set_format_struct(struct v4l2_format *f)
static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd,
struct v4l2_format *format)
{
-#if 0
- u32 const pixfmt = format->fmt.pix.pixelformat;
- const char *fmt;
-
- if (pixfmt != V4L2_PIX_FMT_MPEG) {
- if (cmd == VIDIOC_TRY_FMT)
- fmt = KERN_ERR "try %c%c%c%c failed\n";
- else
- fmt = KERN_ERR "set %c%c%c%c failed\n";
- } else {
- if (cmd == VIDIOC_TRY_FMT)
- fmt = KERN_ERR "try %c%c%c%c\n";
- else
- fmt = KERN_ERR "set %c%c%c%c\n";
- }
- printk(fmt,
- (pixfmt) & 255,
- (pixfmt >> 8) & 255,
- (pixfmt >> 16) & 255,
- (pixfmt >> 24) & 255);
-#endif
-
if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG)
return -EINVAL;
@@ -276,7 +250,6 @@ static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd,
return 0;
}
-
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
@@ -430,7 +403,7 @@ static struct most_video_dev *get_aim_dev(
}
}
spin_unlock(&list_lock);
- return 0;
+ return NULL;
}
static int aim_rx_data(struct mbo *mbo)
@@ -496,7 +469,6 @@ static void aim_unregister_videodev(struct most_video_dev *mdev)
video_unregister_device(mdev->vdev);
}
-
static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev)
{
struct most_video_dev *mdev =
@@ -590,14 +562,16 @@ static int aim_disconnect_channel(struct most_interface *iface,
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);
-
- aim_info.name = "v4l";
- aim_info.probe_channel = aim_probe_channel;
- aim_info.disconnect_channel = aim_disconnect_channel;
- aim_info.rx_completion = aim_rx_data;
return most_register_aim(&aim_info);
}
diff --git a/drivers/staging/most/hdm-dim2/Kconfig b/drivers/staging/most/hdm-dim2/Kconfig
index fc548769479b..28a0e1791600 100644
--- a/drivers/staging/most/hdm-dim2/Kconfig
+++ b/drivers/staging/most/hdm-dim2/Kconfig
@@ -9,7 +9,7 @@ config HDM_DIM2
---help---
Say Y here if you want to connect via MediaLB to network transceiver.
- This device driver is platform dependent and needs an addtional
+ This device driver is platform dependent and needs an additional
platform driver to be installed. For more information contact
maintainer of this driver.
diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c
index a54cf2cedac3..c915c44f025e 100644
--- a/drivers/staging/most/hdm-dim2/dim2_hal.c
+++ b/drivers/staging/most/hdm-dim2/dim2_hal.c
@@ -19,7 +19,6 @@
#include "dim2_reg.h"
#include <linux/stddef.h>
-
/*
* The number of frames per sub-buffer for synchronous channels.
* Allowed values: 1, 2, 4, 8, 16, 32, 64.
@@ -51,7 +50,6 @@
*/
#define DBR_MAP_SIZE 2
-
/* -------------------------------------------------------------------------- */
/* not configurable area */
@@ -60,10 +58,9 @@
#define MLB_CAT 0x80
#define AHB_CAT 0x88
-#define DBR_SIZE (16*1024) /* specified by IP */
+#define DBR_SIZE (16 * 1024) /* specified by IP */
#define DBR_BLOCK_SIZE (DBR_SIZE / 32 / DBR_MAP_SIZE)
-
/* -------------------------------------------------------------------------- */
/* generic helper functions and macros */
@@ -81,7 +78,6 @@ static inline bool dim_on_error(u8 error_id, const char *error_message)
return false;
}
-
/* -------------------------------------------------------------------------- */
/* types and local variables */
@@ -94,7 +90,6 @@ struct lld_global_vars_t {
static struct lld_global_vars_t g = { false };
-
/* -------------------------------------------------------------------------- */
static int dbr_get_mask_size(u16 size)
@@ -134,7 +129,7 @@ static int alloc_dbr(u16 size)
return block_idx * DBR_BLOCK_SIZE;
}
block_idx += mask_size;
- /* do shift left with 2 steps for case mask_size == 32 */
+ /* do shift left with 2 steps in case mask_size == 32 */
mask <<= mask_size - 1;
} while ((mask <<= 1) != 0);
}
@@ -327,7 +322,6 @@ static void dim2_start_isoc_sync(u8 ch_addr, u8 idx, u32 buf_addr,
dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
}
-
static void dim2_clear_ctram(void)
{
u32 ctr_addr;
@@ -499,22 +493,6 @@ static void dim2_initialize(bool enable_6pin, u8 mlb_clock)
DIMCB_IoWrite(&g.dim2->ACTL,
ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT |
true << ACTL_SCE_BIT);
-
-#if 0
- DIMCB_IoWrite(&g.dim2->MIEN,
- bit_mask(MIEN_CTX_BREAK_BIT) |
- bit_mask(MIEN_CTX_PE_BIT) |
- bit_mask(MIEN_CTX_DONE_BIT) |
- bit_mask(MIEN_CRX_BREAK_BIT) |
- bit_mask(MIEN_CRX_PE_BIT) |
- bit_mask(MIEN_CRX_DONE_BIT) |
- bit_mask(MIEN_ATX_BREAK_BIT) |
- bit_mask(MIEN_ATX_PE_BIT) |
- bit_mask(MIEN_ATX_DONE_BIT) |
- bit_mask(MIEN_ARX_BREAK_BIT) |
- bit_mask(MIEN_ARX_PE_BIT) |
- bit_mask(MIEN_ARX_DONE_BIT));
-#endif
}
static bool dim2_is_mlb_locked(void)
@@ -530,7 +508,6 @@ static bool dim2_is_mlb_locked(void)
(DIMCB_IoRead(&g.dim2->MLBC0) & mask0) != 0;
}
-
/* -------------------------------------------------------------------------- */
/* channel help routines */
@@ -559,7 +536,6 @@ static inline bool service_channel(u8 ch_addr, u8 idx)
return true;
}
-
/* -------------------------------------------------------------------------- */
/* channel init routines */
@@ -639,7 +615,8 @@ static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 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);
+ dim2_start_ctrl_async(ch->addr, state->idx1, buf_addr,
+ buf_size);
state->idx1 ^= 1;
return true;
@@ -670,7 +647,6 @@ static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number)
return true;
}
-
/* -------------------------------------------------------------------------- */
/* API */
@@ -687,7 +663,8 @@ u8 DIM_Startup(void *dim_base_address, u32 mlb_clock)
return DIM_INIT_ERR_MLB_CLOCK;
g.dim2 = dim_base_address;
- g.dbr_map[0] = g.dbr_map[1] = 0;
+ g.dbr_map[0] = 0;
+ g.dbr_map[1] = 0;
dim2_initialize(mlb_clock >= 3, mlb_clock);
@@ -766,14 +743,14 @@ u8 DIM_InitControl(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 * 2);
+ max_buffer_size);
}
u8 DIM_InitAsync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
u16 max_buffer_size)
{
return init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address,
- max_buffer_size * 2);
+ max_buffer_size);
}
u8 DIM_InitIsoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
@@ -855,11 +832,11 @@ void DIM_ServiceIrq(struct dim_channel *const *channels)
}
/*
- * 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 service_interrupts
- * routine doesn't start the channel again.
+ * 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;
@@ -886,7 +863,7 @@ u8 DIM_ServiceChannel(struct dim_channel *ch)
}
struct dim_ch_state_t *DIM_GetChannelState(struct dim_channel *ch,
- struct dim_ch_state_t *state_ptr)
+ struct dim_ch_state_t *state_ptr)
{
if (!ch || !state_ptr)
return NULL;
@@ -900,7 +877,8 @@ struct dim_ch_state_t *DIM_GetChannelState(struct dim_channel *ch,
bool DIM_EnqueueBuffer(struct dim_channel *ch, u32 buffer_addr, u16 buffer_size)
{
if (!ch)
- return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channel");
+ return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
+ "Bad channel");
return channel_start(ch, buffer_addr, buffer_size);
}
@@ -908,12 +886,8 @@ bool DIM_EnqueueBuffer(struct dim_channel *ch, u32 buffer_addr, u16 buffer_size)
bool DIM_DetachBuffers(struct dim_channel *ch, u16 buffers_number)
{
if (!ch)
- return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channel");
+ return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
+ "Bad channel");
return channel_detach_buffers(ch, buffers_number);
}
-
-u32 DIM_ReadRegister(u8 register_index)
-{
- return DIMCB_IoRead((u32 *)g.dim2 + register_index);
-}
diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h
index 8929af9712ef..ebb7d87a45fc 100644
--- a/drivers/staging/most/hdm-dim2/dim2_hal.h
+++ b/drivers/staging/most/hdm-dim2/dim2_hal.h
@@ -105,17 +105,12 @@ bool DIM_EnqueueBuffer(struct dim_channel *ch, u32 buffer_addr,
bool DIM_DetachBuffers(struct dim_channel *ch, u16 buffers_number);
-u32 DIM_ReadRegister(u8 register_index);
-
-
u32 DIMCB_IoRead(u32 *ptr32);
void DIMCB_IoWrite(u32 *ptr32, u32 value);
void DIMCB_OnError(u8 error_id, const char *error_message);
-void DIMCB_OnFail(const char *filename, int linenum);
-
#ifdef __cplusplus
}
diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c
index 6a5a3a2775f3..b6fe346f73b0 100644
--- a/drivers/staging/most/hdm-dim2/dim2_hdm.c
+++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c
@@ -37,7 +37,7 @@
#define MAX_BUFFERS_PACKET 32
#define MAX_BUFFERS_STREAMING 32
#define MAX_BUF_SIZE_PACKET 2048
-#define MAX_BUF_SIZE_STREAMING (8*1024)
+#define MAX_BUF_SIZE_STREAMING (8 * 1024)
/* command line parameter to select clock speed */
static char *clock_speed;
@@ -166,16 +166,6 @@ void DIMCB_OnError(u8 error_id, const char *error_message)
}
/**
- * DIMCB_OnFail - callback from HAL to report unrecoverable errors
- * @filename: Source file where the error happened
- * @linenum: Line number of the file where the error happened
- */
-void DIMCB_OnFail(const char *filename, int linenum)
-{
- pr_err("DIMCB_OnFail: file - %s, line no. - %d\n", filename, linenum);
-}
-
-/**
* startup_dim - initialize the dim2 interface
* @pdev: platform device
*
@@ -210,12 +200,11 @@ static int startup_dim(struct platform_device *pdev)
}
if (dev->clk_speed == -1) {
- pr_info("Bad or missing clock speed parameter,"
- " using default value: 3072fs\n");
+ pr_info("Bad or missing clock speed parameter, using default value: 3072fs\n");
dev->clk_speed = CLK_3072FS;
- } else
+ } 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);
@@ -248,7 +237,7 @@ static int try_start_dim_transfer(struct hdm_channel *hdm_ch)
unsigned long flags;
struct dim_ch_state_t st;
- BUG_ON(hdm_ch == 0);
+ BUG_ON(!hdm_ch);
BUG_ON(!hdm_ch->is_initialized);
spin_lock_irqsave(&dim_lock, flags);
@@ -289,7 +278,7 @@ static int try_start_dim_transfer(struct hdm_channel *hdm_ch)
*/
static int deliver_netinfo_thread(void *data)
{
- struct dim2_hdm *dev = (struct dim2_hdm *)data;
+ struct dim2_hdm *dev = data;
while (!kthread_should_stop()) {
wait_event_interruptible(dev->netinfo_waitq,
@@ -346,7 +335,7 @@ static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
unsigned long flags;
u8 *data;
- BUG_ON(hdm_ch == 0);
+ BUG_ON(!hdm_ch);
BUG_ON(!hdm_ch->is_initialized);
spin_lock_irqsave(&dim_lock, flags);
@@ -369,8 +358,7 @@ static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
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");
+ pr_crit("hard error: started_mbo list is empty whereas DIM2 has sent buffers\n");
break;
}
@@ -397,7 +385,8 @@ static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
(u32)data[0] * 256 + data[1] + 2;
mbo->processed_length =
- min(data_size, (u32)mbo->buffer_length);
+ min_t(u32, data_size,
+ mbo->buffer_length);
} else {
mbo->processed_length = mbo->buffer_length;
}
@@ -410,7 +399,7 @@ static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
}
static struct dim_channel **get_active_channels(struct dim2_hdm *dev,
- struct dim_channel **buffer)
+ struct dim_channel **buffer)
{
int idx = 0;
int ch_idx;
@@ -419,7 +408,7 @@ static struct dim_channel **get_active_channels(struct dim2_hdm *dev,
if (dev->hch[ch_idx].is_initialized)
buffer[idx++] = &dev->hch[ch_idx].ch;
}
- buffer[idx++] = 0;
+ buffer[idx++] = NULL;
return buffer;
}
@@ -441,7 +430,7 @@ static void dim2_tasklet_fn(unsigned long data)
continue;
spin_lock_irqsave(&dim_lock, flags);
- DIM_ServiceChannel(&(dev->hch[ch_idx].ch));
+ DIM_ServiceChannel(&dev->hch[ch_idx].ch);
spin_unlock_irqrestore(&dim_lock, flags);
service_done_flag(dev, ch_idx);
@@ -460,7 +449,7 @@ static void dim2_tasklet_fn(unsigned long data)
*/
static irqreturn_t dim2_ahb_isr(int irq, void *_dev)
{
- struct dim2_hdm *dev = (struct dim2_hdm *)_dev;
+ struct dim2_hdm *dev = _dev;
struct dim_channel *buffer[DMA_CHANNELS + 1];
unsigned long flags;
@@ -557,7 +546,8 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx,
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_InitControl(&hdm_ch->ch, is_tx, ch_addr, buf_size);
+ hal_ret = DIM_InitControl(&hdm_ch->ch, is_tx, ch_addr,
+ buf_size);
break;
case MOST_CH_ASYNC:
new_size = DIM_NormCtrlAsyncBufferSize(buf_size);
@@ -575,8 +565,8 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx,
case MOST_CH_ISOC_AVP:
new_size = DIM_NormIsocBufferSize(buf_size, sub_size);
if (new_size == 0) {
- pr_err("%s: invalid sub-buffer size or "
- "too small buffer size\n", hdm_ch->name);
+ pr_err("%s: invalid sub-buffer size or too small buffer size\n",
+ hdm_ch->name);
return -EINVAL;
}
ccfg->buffer_size = new_size;
@@ -589,8 +579,8 @@ static int configure_channel(struct most_interface *most_iface, int ch_idx,
case MOST_CH_SYNC:
new_size = DIM_NormSyncBufferSize(buf_size, sub_size);
if (new_size == 0) {
- pr_err("%s: invalid sub-buffer size or "
- "too small buffer size\n", hdm_ch->name);
+ pr_err("%s: invalid sub-buffer size or too small buffer size\n",
+ hdm_ch->name);
return -EINVAL;
}
ccfg->buffer_size = new_size;
@@ -679,7 +669,7 @@ static void request_netinfo(struct most_interface *most_iface, int ch_idx)
return;
}
- mbo = most_get_mbo(&dev->most_iface, dev->atx_idx);
+ mbo = most_get_mbo(&dev->most_iface, dev->atx_idx, NULL);
if (!mbo)
return;
@@ -787,7 +777,8 @@ static int dim2_probe(struct platform_device *pdev)
ret = request_irq(dev->irq_ahb0, dim2_ahb_isr, 0, "mlb_ahb0", dev);
if (ret) {
- pr_err("failed to request IRQ: %d, err: %d\n", dev->irq_ahb0, ret);
+ pr_err("failed to request IRQ: %d, err: %d\n",
+ dev->irq_ahb0, ret);
goto err_unmap_io;
}
#endif
@@ -915,7 +906,7 @@ static int dim2_remove(struct platform_device *pdev)
* break link to local platform_device_id struct
* to prevent crash by unload platform device module
*/
- pdev->id_entry = 0;
+ pdev->id_entry = NULL;
return 0;
}
@@ -933,30 +924,10 @@ static struct platform_driver dim2_driver = {
.id_table = dim2_id,
.driver = {
.name = "hdm_dim2",
- .owner = THIS_MODULE,
},
};
-/**
- * dim2_hdm_init - Driver Registration Routine
- */
-static int __init dim2_hdm_init(void)
-{
- pr_info("dim2_hdm_init()\n");
- return platform_driver_register(&dim2_driver);
-}
-
-/**
- * dim2_hdm_exit - Driver Cleanup Routine
- **/
-static void __exit dim2_hdm_exit(void)
-{
- pr_info("dim2_hdm_exit()\n");
- platform_driver_unregister(&dim2_driver);
-}
-
-module_init(dim2_hdm_init);
-module_exit(dim2_hdm_exit);
+module_platform_driver(dim2_driver);
MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.h b/drivers/staging/most/hdm-dim2/dim2_hdm.h
index 6e6883232809..1c94e3355fcc 100644
--- a/drivers/staging/most/hdm-dim2/dim2_hdm.h
+++ b/drivers/staging/most/hdm-dim2/dim2_hdm.h
@@ -18,7 +18,8 @@ struct device;
/* platform dependent data for dim2 interface */
struct dim2_platform_data {
- int (*init)(struct dim2_platform_data *pd, void *io_base, int clk_speed);
+ int (*init)(struct dim2_platform_data *pd, void *io_base,
+ int clk_speed);
void (*destroy)(struct dim2_platform_data *pd);
void *priv;
};
diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.c b/drivers/staging/most/hdm-dim2/dim2_sysfs.c
index 8e331a286fc3..c5b10c7d2fac 100644
--- a/drivers/staging/most/hdm-dim2/dim2_sysfs.c
+++ b/drivers/staging/most/hdm-dim2/dim2_sysfs.c
@@ -21,7 +21,8 @@
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);
+ ssize_t (*store)(struct medialb_bus *bus, const char *buf,
+ size_t count);
};
static ssize_t state_show(struct medialb_bus *bus, char *buf)
diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/hdm-i2c/hdm_i2c.c
index 029ded3f250b..ba0263bb3d12 100644
--- a/drivers/staging/most/hdm-i2c/hdm_i2c.c
+++ b/drivers/staging/most/hdm-i2c/hdm_i2c.c
@@ -35,7 +35,6 @@ enum { CH_RX, CH_TX, NUM_CHANNELS };
#define list_first_mbo(ptr) \
list_first_entry(ptr, struct mbo, list)
-
/* IRQ / Polling option */
static bool polling_req;
module_param(polling_req, bool, S_IRUGO);
@@ -93,10 +92,9 @@ static int configure_channel(struct most_interface *most_iface,
return -EPERM;
}
- if (channel_config->direction == MOST_CH_RX) {
- if (dev->polling_mode)
- schedule_delayed_work(&dev->rx.dwork,
- msecs_to_jiffies(MSEC_PER_SEC / 4));
+ 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;
@@ -198,7 +196,7 @@ 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;
- uint16_t pml, data_size;
+ u16 pml, data_size;
/* Read PML (2 bytes) */
ret = i2c_master_recv(dev->client, msg, 2);
@@ -222,7 +220,8 @@ static void do_rx_work(struct hdm_i2c *dev)
for (;;) {
/* Conditions to wait for: poisoned channel or free buffer
- available for reading */
+ * available for reading
+ */
if (wait_event_interruptible(dev->rx.waitq,
!dev->is_open[ch_idx] ||
!list_empty(&dev->rx.list))) {
@@ -269,8 +268,9 @@ static void pending_rx_work(struct work_struct *work)
schedule_delayed_work(&dev->rx.dwork,
msecs_to_jiffies(MSEC_PER_SEC
/ scan_rate));
- } else
+ } else {
enable_irq(dev->client->irq);
+ }
}
/*
@@ -364,11 +364,11 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
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, IRQF_SHARED,
+ 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);
+ pr_info("IRQ request failed: %d, falling back to polling\n",
+ ret);
dev->polling_mode = true;
}
}
@@ -416,34 +416,13 @@ MODULE_DEVICE_TABLE(i2c, i2c_id);
static struct i2c_driver i2c_driver = {
.driver = {
.name = "hdm_i2c",
- .owner = THIS_MODULE,
},
.probe = i2c_probe,
.remove = i2c_remove,
.id_table = i2c_id,
};
-/**
- * hdm_i2c_init - Driver Registration Routine
- */
-static int __init hdm_i2c_init(void)
-{
- pr_info("hdm_i2c_init()\n");
-
- return i2c_add_driver(&i2c_driver);
-}
-
-/**
- * hdm_i2c_exit - Driver Cleanup Routine
- **/
-static void __exit hdm_i2c_exit(void)
-{
- i2c_del_driver(&i2c_driver);
- pr_info("hdm_i2c_exit()\n");
-}
-
-module_init(hdm_i2c_init);
-module_exit(hdm_i2c_exit);
+module_i2c_driver(i2c_driver);
MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c
index 305303f2f17c..41690f801fb8 100644
--- a/drivers/staging/most/hdm-usb/hdm_usb.c
+++ b/drivers/staging/most/hdm-usb/hdm_usb.c
@@ -59,6 +59,8 @@
#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
@@ -75,6 +77,7 @@ struct buf_anchor {
struct list_head list;
struct completion urb_compl;
};
+
#define to_buf_anchor(w) container_of(w, struct buf_anchor, clear_work_obj)
/**
@@ -86,6 +89,7 @@ struct most_dci_obj {
struct kobject kobj;
struct usb_device *usb_device;
};
+
#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj)
/**
@@ -129,6 +133,7 @@ struct most_dev {
struct timer_list link_stat_timer;
struct work_struct poll_work_obj;
};
+
#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)
@@ -137,36 +142,6 @@ static void wq_clear_halt(struct work_struct *wq_obj);
static void wq_netinfo(struct work_struct *wq_obj);
/**
- * trigger_resync_vr - Vendor request to trigger HW re-sync mechanism
- * @dev: usb device
- *
- */
-static void trigger_resync_vr(struct usb_device *dev)
-{
- int retval;
- u8 request_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
- int *data = kzalloc(sizeof(*data), GFP_KERNEL);
-
- if (!data)
- goto error;
- *data = HW_RESYNC;
- retval = usb_control_msg(dev,
- usb_sndctrlpipe(dev, 0),
- 0,
- request_type,
- 0,
- 0,
- data,
- 0,
- 5 * HZ);
- kfree(data);
- if (retval >= 0)
- return;
-error:
- dev_err(&dev->dev, "Vendor request \"stall\" failed\n");
-}
-
-/**
* drci_rd_reg - read a DCI register
* @dev: usb device
* @reg: register address
@@ -174,17 +149,23 @@ error:
*
* This is reads data from INIC's direct register communication interface
*/
-static inline int drci_rd_reg(struct usb_device *dev, u16 reg, void *buf)
+static inline int drci_rd_reg(struct usb_device *dev, u16 reg, u16 *buf)
{
- return usb_control_msg(dev,
- usb_rcvctrlpipe(dev, 0),
- DRCI_READ_REQ,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0x0000,
- reg,
- buf,
- 2,
- 5 * HZ);
+ int retval;
+ u16 *dma_buf = kzalloc(sizeof(u16), 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(u16), 5 * HZ);
+ *buf = le16_to_cpu(*dma_buf);
+ kfree(dma_buf);
+
+ return retval;
}
/**
@@ -220,7 +201,8 @@ static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel)
unsigned long flags;
spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
- list_for_each_entry_safe(anchor, tmp, &mdev->anchor_list[channel], list) {
+ list_for_each_entry_safe(anchor, tmp, &mdev->anchor_list[channel],
+ list) {
struct urb *urb = anchor->urb;
spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
@@ -267,10 +249,11 @@ static unsigned int get_stream_frame_size(struct most_channel_config *cfg)
if (cfg->packets_per_xact == 0) {
pr_warn("Misconfig: Packets per XACT zero\n");
frame_size = 0;
- } else if (cfg->packets_per_xact == 0xFF)
+ } else if (cfg->packets_per_xact == 0xFF) {
frame_size = (USB_MTU / sub_size) * sub_size;
- else
+ } else {
frame_size = cfg->packets_per_xact * sub_size;
+ }
break;
default:
pr_warn("Query frame size of non-streaming channel\n");
@@ -308,7 +291,7 @@ static int hdm_poison_channel(struct most_interface *iface, int channel)
mutex_lock(&mdev->io_mutex);
free_anchored_buffers(mdev, channel);
- if (mdev->padding_active[channel] == true)
+ if (mdev->padding_active[channel])
mdev->padding_active[channel] = false;
if (mdev->conf[channel].data_type == MOST_CH_ASYNC) {
@@ -365,7 +348,8 @@ static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo)
* 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)
+static int hdm_remove_padding(struct most_dev *mdev, int channel,
+ struct mbo *mbo)
{
unsigned int j, num_frames, frame_size;
struct most_channel_config *const conf = &mdev->conf[channel];
@@ -411,7 +395,7 @@ static void hdm_write_completion(struct urb *urb)
dev = &mdev->usb_device->dev;
if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) ||
- (mdev->is_channel_healthy[channel] == false)) {
+ (!mdev->is_channel_healthy[channel])) {
complete(&anchor->urb_compl);
return;
}
@@ -453,7 +437,7 @@ static void hdm_write_completion(struct urb *urb)
}
/**
- * hdm_read_completion - completion funciton for submitted Rx URBs
+ * 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
@@ -568,7 +552,6 @@ static void hdm_read_completion(struct urb *urb)
struct device *dev;
unsigned long flags;
unsigned int channel;
- struct most_channel_config *conf;
mbo = urb->context;
anchor = mbo->priv;
@@ -577,13 +560,11 @@ static void hdm_read_completion(struct urb *urb)
dev = &mdev->usb_device->dev;
if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) ||
- (mdev->is_channel_healthy[channel] == false)) {
+ (!mdev->is_channel_healthy[channel])) {
complete(&anchor->urb_compl);
return;
}
- conf = &mdev->conf[channel];
-
if (unlikely(urb->status && !(urb->status == -ENOENT ||
urb->status == -ECONNRESET ||
urb->status == -ESHUTDOWN))) {
@@ -608,7 +589,7 @@ static void hdm_read_completion(struct urb *urb)
}
} else {
mbo->processed_length = urb->actual_length;
- if (mdev->padding_active[channel] == false) {
+ if (!mdev->padding_active[channel]) {
mbo->status = MBO_SUCCESS;
} else {
if (hdm_remove_padding(mdev, channel, mbo)) {
@@ -644,7 +625,8 @@ static void hdm_read_completion(struct urb *urb)
*
* Context: Could in _some_ cases be interrupt!
*/
-static int hdm_enqueue(struct most_interface *iface, int channel, struct mbo *mbo)
+static int hdm_enqueue(struct most_interface *iface, int channel,
+ struct mbo *mbo)
{
struct most_dev *mdev;
struct buf_anchor *anchor;
@@ -688,7 +670,7 @@ static int hdm_enqueue(struct most_interface *iface, int channel, struct mbo *mb
list_add_tail(&anchor->list, &mdev->anchor_list[channel]);
spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
- if ((mdev->padding_active[channel] == true) &&
+ if ((mdev->padding_active[channel]) &&
(conf->direction & MOST_CH_TX))
if (hdm_add_padding(mdev, channel, mbo)) {
retval = -EIO;
@@ -714,7 +696,7 @@ static int hdm_enqueue(struct most_interface *iface, int channel, struct mbo *mb
usb_rcvbulkpipe(mdev->usb_device,
mdev->ep_address[channel]),
virt_address,
- length,
+ length + conf->extra_len,
hdm_read_completion,
mbo);
}
@@ -780,12 +762,6 @@ static int hdm_configure_channel(struct most_interface *iface, int channel,
mdev->padding_active[channel] = true;
temp_size = conf->buffer_size;
- if ((conf->data_type != MOST_CH_SYNC) &&
- (conf->data_type != MOST_CH_ISOC_AVP)) {
- dev_warn(dev, "Unsupported data type\n");
- return -EINVAL;
- }
-
frame_size = get_stream_frame_size(conf);
if ((frame_size == 0) || (frame_size > USB_MTU)) {
dev_warn(dev, "Misconfig: frame size wrong\n");
@@ -798,8 +774,7 @@ static int hdm_configure_channel(struct most_interface *iface, int channel,
tmp_val = conf->buffer_size / frame_size;
conf->buffer_size = tmp_val * frame_size;
dev_notice(dev,
- "Channel %d - rouding buffer size to %d bytes, "
- "channel config says %d bytes\n",
+ "Channel %d - rounding buffer size to %d bytes, channel config says %d bytes\n",
channel,
conf->buffer_size,
temp_size);
@@ -826,38 +801,41 @@ exit:
*/
static int hdm_update_netinfo(struct most_dev *mdev)
{
- struct device *dev = &mdev->usb_device->dev;
- int i;
- u16 link;
- u8 addr[6];
+ struct usb_device *usb_device = mdev->usb_device;
+ struct device *dev = &usb_device->dev;
+ u16 hi, mi, lo, link;
if (!is_valid_ether_addr(mdev->hw_addr)) {
- if (0 > drci_rd_reg(mdev->usb_device,
- DRCI_REG_HW_ADDR_HI, addr)) {
+ if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_HI, &hi) < 0) {
dev_err(dev, "Vendor request \"hw_addr_hi\" failed\n");
return -1;
}
- if (0 > drci_rd_reg(mdev->usb_device,
- DRCI_REG_HW_ADDR_MI, addr + 2)) {
+
+ if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_MI, &mi) < 0) {
dev_err(dev, "Vendor request \"hw_addr_mid\" failed\n");
return -1;
}
- if (0 > drci_rd_reg(mdev->usb_device,
- DRCI_REG_HW_ADDR_LO, addr + 4)) {
+
+ if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_LO, &lo) < 0) {
dev_err(dev, "Vendor request \"hw_addr_low\" failed\n");
return -1;
}
+
mutex_lock(&mdev->io_mutex);
- for (i = 0; i < 6; i++)
- mdev->hw_addr[i] = addr[i];
+ mdev->hw_addr[0] = hi >> 8;
+ mdev->hw_addr[1] = hi;
+ mdev->hw_addr[2] = mi >> 8;
+ mdev->hw_addr[3] = mi;
+ mdev->hw_addr[4] = lo >> 8;
+ mdev->hw_addr[5] = lo;
mutex_unlock(&mdev->io_mutex);
-
}
- if (0 > drci_rd_reg(mdev->usb_device, DRCI_REG_NI_STATE, &link)) {
+
+ if (drci_rd_reg(usb_device, DRCI_REG_NI_STATE, &link) < 0) {
dev_err(dev, "Vendor request \"link status\" failed\n");
return -1;
}
- le16_to_cpus(&link);
+
mutex_lock(&mdev->io_mutex);
mdev->link_stat = link;
mutex_unlock(&mdev->io_mutex);
@@ -919,7 +897,7 @@ static void wq_netinfo(struct work_struct *wq_obj)
for (i = 0; i < 6; i++)
prev_hw_addr[i] = mdev->hw_addr[i];
- if (0 > hdm_update_netinfo(mdev))
+ if (hdm_update_netinfo(mdev) < 0)
return;
if ((prev_link_stat != mdev->link_stat) ||
(prev_hw_addr[0] != mdev->hw_addr[0]) ||
@@ -1009,8 +987,8 @@ struct most_dci_attribute {
const char *buf,
size_t count);
};
-#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr)
+#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr)
/**
* dci_attr_show - show function for dci object
@@ -1107,14 +1085,14 @@ static ssize_t show_value(struct most_dci_obj *dci_obj,
if (err < 0)
return err;
- return snprintf(buf, PAGE_SIZE, "%04x\n", le16_to_cpu(tmp_val));
+ return snprintf(buf, PAGE_SIZE, "%04x\n", tmp_val);
}
static ssize_t store_value(struct most_dci_obj *dci_obj,
struct most_dci_attribute *attr,
const char *buf, size_t count)
{
- u16 v16;
+ u16 val;
u16 reg_addr;
int err;
@@ -1137,11 +1115,11 @@ static ssize_t store_value(struct most_dci_obj *dci_obj,
else
return -EIO;
- err = kstrtou16(buf, 16, &v16);
+ err = kstrtou16(buf, 16, &val);
if (err)
return err;
- err = drci_wr_reg(dci_obj->usb_device, reg_addr, cpu_to_le16(v16));
+ err = drci_wr_reg(dci_obj->usb_device, reg_addr, val);
if (err < 0)
return err;
@@ -1248,6 +1226,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
struct usb_host_interface *usb_iface_desc;
struct usb_endpoint_descriptor *ep_desc;
int ret = 0;
+ int err;
usb_iface_desc = interface->cur_altsetting;
usb_dev = interface_to_usbdev(interface);
@@ -1260,11 +1239,10 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
num_endpoints = usb_iface_desc->desc.bNumEndpoints;
mutex_init(&mdev->io_mutex);
INIT_WORK(&mdev->poll_work_obj, wq_netinfo);
- init_timer(&mdev->link_stat_timer);
+ setup_timer(&mdev->link_stat_timer, link_stat_timer_handler,
+ (unsigned long)mdev);
mdev->usb_device = usb_dev;
- mdev->link_stat_timer.function = link_stat_timer_handler;
- mdev->link_stat_timer.data = (unsigned long)mdev;
mdev->link_stat_timer.expires = jiffies + (2 * HZ);
mdev->iface.mod = hdm_usb_fops.owner;
@@ -1328,6 +1306,13 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
tmp_cap++;
INIT_LIST_HEAD(&mdev->anchor_list[i]);
spin_lock_init(&mdev->anchor_list_lock[i]);
+ err = drci_wr_reg(usb_dev,
+ DRCI_REG_BASE + DRCI_COMMAND +
+ ep_desc->bEndpointAddress * 16,
+ 1);
+ if (err < 0)
+ pr_warn("DCI Sync for EP %02x failed",
+ ep_desc->bEndpointAddress);
}
dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n",
le16_to_cpu(usb_dev->descriptor.idVendor),
@@ -1362,7 +1347,6 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
kobject_uevent(&mdev->dci->kobj, KOBJ_ADD);
mdev->dci->usb_device = mdev->usb_device;
- trigger_resync_vr(usb_dev);
}
mutex_unlock(&mdev->io_mutex);
return 0;
@@ -1432,7 +1416,7 @@ static int __init hdm_usb_init(void)
return -EIO;
}
schedule_usb_work = create_workqueue("hdmu_work");
- if (schedule_usb_work == NULL) {
+ if (!schedule_usb_work) {
pr_err("could not create workqueue\n");
usb_deregister(&hdm_usb);
return -ENOMEM;
diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c
index 7bb16db42893..19852ca7e59c 100644
--- a/drivers/staging/most/mostcore/core.c
+++ b/drivers/staging/most/mostcore/core.c
@@ -36,15 +36,22 @@ static struct class *most_class;
static struct device *class_glue_dir;
static struct ida mdev_id;
static int modref;
+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;
- uint16_t channel_id;
+ u16 channel_id;
bool is_poisoned;
- bool is_started;
+ struct mutex start_mutex;
int is_starving;
struct most_interface *iface;
struct most_inst_obj *inst;
@@ -55,13 +62,14 @@ struct most_c_obj {
spinlock_t fifo_lock;
struct list_head halt_fifo;
struct list_head list;
- struct most_aim *first_aim;
- struct most_aim *second_aim;
+ struct most_c_aim_obj aim0;
+ struct most_c_aim_obj aim1;
struct list_head trash_fifo;
struct task_struct *hdm_enqueue_task;
struct mutex stop_task_mutex;
wait_queue_head_t hdm_fifo_wq;
};
+
#define to_c_obj(d) container_of(d, struct most_c_obj, kobj)
struct most_inst_obj {
@@ -73,6 +81,7 @@ struct most_inst_obj {
struct kobject kobj;
struct list_head list;
};
+
#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj)
/**
@@ -108,6 +117,7 @@ struct most_c_attr {
const char *buf,
size_t count);
};
+
#define to_channel_attr(a) container_of(a, struct most_c_attr, attr)
#define MOST_CHNL_ATTR(_name, _mode, _show, _store) \
@@ -190,8 +200,7 @@ static void flush_channel_fifos(struct most_c_obj *c)
list_for_each_entry_safe(mbo, tmp, &c->fifo, list) {
list_del(&mbo->list);
spin_unlock_irqrestore(&c->fifo_lock, flags);
- if (likely(mbo))
- most_free_mbo_coherent(mbo);
+ most_free_mbo_coherent(mbo);
spin_lock_irqsave(&c->fifo_lock, flags);
}
spin_unlock_irqrestore(&c->fifo_lock, flags);
@@ -200,8 +209,7 @@ static void flush_channel_fifos(struct most_c_obj *c)
list_for_each_entry_safe(mbo, tmp, &c->halt_fifo, list) {
list_del(&mbo->list);
spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
- if (likely(mbo))
- most_free_mbo_coherent(mbo);
+ most_free_mbo_coherent(mbo);
spin_lock_irqsave(&c->fifo_lock, hf_flags);
}
spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
@@ -242,8 +250,8 @@ static void most_channel_release(struct kobject *kobj)
}
static ssize_t show_available_directions(struct most_c_obj *c,
- struct most_c_attr *attr,
- char *buf)
+ struct most_c_attr *attr,
+ char *buf)
{
unsigned int i = c->channel_id;
@@ -326,7 +334,6 @@ static ssize_t show_channel_starving(struct most_c_obj *c,
return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving);
}
-
#define create_show_channel_attribute(val) \
static MOST_CHNL_ATTR(val, S_IRUGO, show_##val, NULL)
@@ -392,11 +399,11 @@ static ssize_t store_set_direction(struct most_c_obj *c,
const char *buf,
size_t count)
{
- if (!strcmp(buf, "dir_rx\n"))
+ if (!strcmp(buf, "dir_rx\n")) {
c->cfg.direction = MOST_CH_RX;
- else if (!strcmp(buf, "dir_tx\n"))
+ } else if (!strcmp(buf, "dir_tx\n")) {
c->cfg.direction = MOST_CH_TX;
- else {
+ } else {
pr_info("WARN: invalid attribute settings\n");
return -EINVAL;
}
@@ -423,15 +430,15 @@ static ssize_t store_set_datatype(struct most_c_obj *c,
const char *buf,
size_t count)
{
- if (!strcmp(buf, "control\n"))
+ if (!strcmp(buf, "control\n")) {
c->cfg.data_type = MOST_CH_CONTROL;
- else if (!strcmp(buf, "async\n"))
+ } else if (!strcmp(buf, "async\n")) {
c->cfg.data_type = MOST_CH_ASYNC;
- else if (!strcmp(buf, "sync\n"))
+ } else if (!strcmp(buf, "sync\n")) {
c->cfg.data_type = MOST_CH_SYNC;
- else if (!strcmp(buf, "isoc_avp\n"))
+ } else if (!strcmp(buf, "isoc_avp\n")) {
c->cfg.data_type = MOST_CH_ISOC_AVP;
- else {
+ } else {
pr_info("WARN: invalid attribute settings\n");
return -EINVAL;
}
@@ -488,7 +495,6 @@ create_channel_attribute(set_datatype);
create_channel_attribute(set_subbuffer_size);
create_channel_attribute(set_packets_per_xact);
-
/**
* most_channel_def_attrs - array of default attributes of channel object
*/
@@ -554,12 +560,12 @@ create_most_c_obj(const char *name, struct kobject *parent)
*/
static void destroy_most_c_obj(struct most_c_obj *c)
{
- if (c->first_aim)
- c->first_aim->disconnect_channel(c->iface, c->channel_id);
- if (c->second_aim)
- c->second_aim->disconnect_channel(c->iface, c->channel_id);
- c->first_aim = NULL;
- c->second_aim = NULL;
+ 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;
mutex_lock(&deregister_mutex);
flush_trash_fifo(c);
@@ -593,6 +599,7 @@ struct most_inst_attribute {
const char *buf,
size_t count);
};
+
#define to_instance_attr(a) \
container_of(a, struct most_inst_attribute, attr)
@@ -715,7 +722,6 @@ static struct kobj_type most_inst_ktype = {
static struct kset *most_inst_kset;
-
/**
* create_most_inst_obj - creates an instance object
* @name: name of the object to be created
@@ -775,11 +781,11 @@ struct most_aim_obj {
char add_link[STRING_SIZE];
char remove_link[STRING_SIZE];
};
+
#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
@@ -796,6 +802,7 @@ struct most_aim_attribute {
const char *buf,
size_t count);
};
+
#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr)
/**
@@ -933,7 +940,7 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
break;
}
}
- if (unlikely(2 > found))
+ if (unlikely(found < 2))
return ERR_PTR(-EIO);
return c;
}
@@ -983,7 +990,8 @@ static ssize_t store_add_link(struct most_aim_obj *aim_obj,
return ret;
if (!mdev_devnod || *mdev_devnod == 0) {
- snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev, mdev_ch);
+ snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev,
+ mdev_ch);
mdev_devnod = devnod_buf;
}
@@ -991,10 +999,10 @@ static ssize_t store_add_link(struct most_aim_obj *aim_obj,
if (IS_ERR(c))
return -ENODEV;
- if (!c->first_aim)
- aim_ptr = &c->first_aim;
- else if (!c->second_aim)
- aim_ptr = &c->second_aim;
+ if (!c->aim0.ptr)
+ aim_ptr = &c->aim0.ptr;
+ else if (!c->aim1.ptr)
+ aim_ptr = &c->aim1.ptr;
else
return -ENOSPC;
@@ -1048,17 +1056,18 @@ static ssize_t store_remove_link(struct most_aim_obj *aim_obj,
if (IS_ERR(c))
return -ENODEV;
- if (c->first_aim == aim_obj->driver)
- c->first_aim = NULL;
- if (c->second_aim == aim_obj->driver)
- c->second_aim = NULL;
+ if (c->aim0.ptr == aim_obj->driver)
+ c->aim0.ptr = NULL;
+ if (c->aim1.ptr == aim_obj->driver)
+ c->aim1.ptr = NULL;
if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id))
return -EIO;
return len;
}
static struct most_aim_attribute most_aim_attr_remove_link =
- __ATTR(remove_link, S_IRUGO | S_IWUSR, show_remove_link, store_remove_link);
+ __ATTR(remove_link, S_IRUGO | S_IWUSR, show_remove_link,
+ store_remove_link);
static struct attribute *most_aim_def_attrs[] = {
&most_aim_attr_add_link.attr,
@@ -1113,7 +1122,6 @@ static void destroy_most_aim_obj(struct most_aim_obj *p)
kobject_put(&p->kobj);
}
-
/* ___ ___
* ___C O R E___
*/
@@ -1176,8 +1184,8 @@ static int hdm_enqueue_thread(void *data)
while (likely(!kthread_should_stop())) {
wait_event_interruptible(c->hdm_fifo_wq,
- (mbo = get_hdm_mbo(c))
- || kthread_should_stop());
+ (mbo = get_hdm_mbo(c)) ||
+ kthread_should_stop());
if (unlikely(!mbo))
continue;
@@ -1199,7 +1207,8 @@ static int hdm_enqueue_thread(void *data)
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);
+ kthread_run(hdm_enqueue_thread, c, "hdm_fifo_%d",
+ channel_id);
if (IS_ERR(task))
return PTR_ERR(task);
@@ -1233,13 +1242,15 @@ static void arm_mbo(struct mbo *mbo)
}
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->second_aim && c->second_aim->tx_completion)
- c->second_aim->tx_completion(c->iface, c->channel_id);
- if (c->first_aim && c->first_aim->tx_completion)
- c->first_aim->tx_completion(c->iface, c->channel_id);
+ 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);
}
/**
@@ -1285,6 +1296,7 @@ static int arm_mbo_chain(struct most_c_obj *c, int dir,
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);
@@ -1341,7 +1353,7 @@ static void most_write_completion(struct mbo *mbo)
c = mbo->context;
if (mbo->status == MBO_E_INVAL)
pr_info("WARN: Tx MBO status: invalid\n");
- if (unlikely((c->is_poisoned == true) || (mbo->status == MBO_E_CLOSE)))
+ if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE)))
trash_mbo(mbo);
else
arm_mbo(mbo);
@@ -1375,6 +1387,22 @@ most_c_obj *get_channel_by_iface(struct most_interface *iface, int id)
return i->channel[id];
}
+int channel_has_mbo(struct most_interface *iface, int id)
+{
+ struct most_c_obj *c = get_channel_by_iface(iface, id);
+ unsigned long flags;
+ int empty;
+
+ if (unlikely(!c))
+ return -EINVAL;
+
+ 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
@@ -1383,28 +1411,45 @@ most_c_obj *get_channel_by_iface(struct most_interface *iface, int 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 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
@@ -1443,11 +1488,12 @@ EXPORT_SYMBOL_GPL(most_put_mbo);
*/
static void most_read_completion(struct mbo *mbo)
{
- struct most_c_obj *c;
+ struct most_c_obj *c = mbo->context;
- c = mbo->context;
- if (unlikely((c->is_poisoned == true) || (mbo->status == MBO_E_CLOSE)))
- goto release_mbo;
+ if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) {
+ trash_mbo(mbo);
+ return;
+ }
if (mbo->status == MBO_E_INVAL) {
nq_hdm_mbo(mbo);
@@ -1460,16 +1506,15 @@ static void most_read_completion(struct mbo *mbo)
c->is_starving = 1;
}
- if (c->first_aim && c->first_aim->rx_completion &&
- c->first_aim->rx_completion(mbo) == 0)
+ if (c->aim0.refs && c->aim0.ptr->rx_completion &&
+ c->aim0.ptr->rx_completion(mbo) == 0)
return;
- if (c->second_aim && c->second_aim->rx_completion &&
- c->second_aim->rx_completion(mbo) == 0)
+
+ if (c->aim1.refs && c->aim1.ptr->rx_completion &&
+ c->aim1.ptr->rx_completion(mbo) == 0)
return;
- pr_info("WARN: no driver linked with this channel\n");
- mbo->status = MBO_E_CLOSE;
-release_mbo:
- trash_mbo(mbo);
+
+ most_put_mbo(mbo);
}
/**
@@ -1482,7 +1527,8 @@ release_mbo:
*
* Returns 0 on success or error code otherwise.
*/
-int most_start_channel(struct most_interface *iface, int id)
+int most_start_channel(struct most_interface *iface, int id,
+ struct most_aim *aim)
{
int num_buffer;
int ret;
@@ -1491,11 +1537,13 @@ int most_start_channel(struct most_interface *iface, int id)
if (unlikely(!c))
return -EINVAL;
- if (c->is_started)
- return -EBUSY;
+ 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;
}
modref++;
@@ -1515,7 +1563,7 @@ int most_start_channel(struct most_interface *iface, int id)
else
num_buffer = arm_mbo_chain(c, c->cfg.direction,
most_write_completion);
- if (unlikely(0 == num_buffer)) {
+ if (unlikely(!num_buffer)) {
pr_info("failed to allocate memory\n");
ret = -ENOMEM;
goto error;
@@ -1525,14 +1573,24 @@ int most_start_channel(struct most_interface *iface, int id)
if (ret)
goto error;
- c->is_started = true;
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:
if (iface->mod)
module_put(iface->mod);
modref--;
+ mutex_unlock(&c->start_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(most_start_channel);
@@ -1542,7 +1600,8 @@ EXPORT_SYMBOL_GPL(most_start_channel);
* @iface: pointer to interface instance
* @id: channel ID
*/
-int most_stop_channel(struct most_interface *iface, int id)
+int most_stop_channel(struct most_interface *iface, int id,
+ struct most_aim *aim)
{
struct most_c_obj *c;
@@ -1554,13 +1613,9 @@ int most_stop_channel(struct most_interface *iface, int id)
if (unlikely(!c))
return -EINVAL;
- if (!c->is_started)
- return 0;
-
- /* FIXME: we need to know calling AIM to reset only one link */
- c->first_aim = NULL;
- c->second_aim = NULL;
- /* do not go into recursion calling aim->disconnect_channel */
+ mutex_lock(&c->start_mutex);
+ if (c->aim0.refs + c->aim1.refs >= 2)
+ goto out;
mutex_lock(&c->stop_task_mutex);
if (c->hdm_enqueue_task)
@@ -1571,6 +1626,7 @@ int most_stop_channel(struct most_interface *iface, int id)
mutex_lock(&deregister_mutex);
if (atomic_read(&c->inst->tainted)) {
mutex_unlock(&deregister_mutex);
+ mutex_unlock(&c->start_mutex);
return -ENODEV;
}
mutex_unlock(&deregister_mutex);
@@ -1584,6 +1640,7 @@ int most_stop_channel(struct most_interface *iface, int id)
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);
@@ -1592,13 +1649,20 @@ int most_stop_channel(struct most_interface *iface, int id)
#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;
- c->is_started = 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);
@@ -1651,13 +1715,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->first_aim == aim || c->second_aim == aim)
+ if (c->aim0.ptr == aim || c->aim1.ptr == aim)
aim->disconnect_channel(
c->iface, c->channel_id);
- if (c->first_aim == aim)
- c->first_aim = NULL;
- if (c->second_aim == aim)
- c->second_aim = NULL;
+ if (c->aim0.ptr == aim)
+ c->aim0.ptr = NULL;
+ if (c->aim1.ptr == aim)
+ c->aim1.ptr = NULL;
}
}
list_del(&aim_obj->list);
@@ -1732,7 +1796,6 @@ struct kobject *most_register_interface(struct most_interface *iface)
c->keep_mbo = false;
c->enqueue_halt = false;
c->is_poisoned = false;
- c->is_started = false;
c->cfg.direction = 0;
c->cfg.data_type = 0;
c->cfg.num_buffers = 0;
@@ -1745,6 +1808,7 @@ struct kobject *most_register_interface(struct most_interface *iface)
INIT_LIST_HEAD(&c->halt_fifo);
init_completion(&c->cleanup);
atomic_set(&c->mbo_ref, 0);
+ mutex_init(&c->start_mutex);
mutex_init(&c->stop_task_mutex);
list_add_tail(&c->list, &inst->channel_list);
}
@@ -1791,7 +1855,7 @@ void most_deregister_interface(struct most_interface *iface)
}
list_for_each_entry(c, &i->channel_list, list) {
- if (!c->is_started)
+ if (c->aim0.refs + c->aim1.refs <= 0)
continue;
mutex_lock(&c->stop_task_mutex);
diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h
index 299c7d5aa73a..e148b324331a 100644
--- a/drivers/staging/most/mostcore/mostcore.h
+++ b/drivers/staging/most/mostcore/mostcore.h
@@ -190,6 +190,7 @@ struct mbo {
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;
@@ -254,7 +255,7 @@ struct most_interface {
* 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: notification that a certain channel isn't available anymore
+ * @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
@@ -307,10 +308,14 @@ void most_stop_enqueue(struct most_interface *iface, int channel_idx);
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 mbo *most_get_mbo(struct most_interface *iface, int channel_idx,
+ struct most_aim *);
void most_put_mbo(struct mbo *mbo);
-int most_start_channel(struct most_interface *iface, int channel_idx);
-int most_stop_channel(struct most_interface *iface, int channel_idx);
+int channel_has_mbo(struct most_interface *iface, int channel_idx);
+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_ */