Commit 2338652c authored by Andrey Shvetsov's avatar Andrey Shvetsov Committed by Greg Kroah-Hartman

staging: most: net: protect consistency of the state

This introduces the mutex that protects the consistency between the
tx.linked, rx.linked and the presence of the net divice.

Additionally, this patch optimizes the setup of the ch->linked in the
function aim_probe_channel.
Signed-off-by: default avatarAndrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: default avatarChristian Gromm <christian.gromm@microchip.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 606c2175
......@@ -72,6 +72,7 @@ struct net_dev_context {
};
static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */
static struct spinlock list_lock;
static struct most_aim aim;
......@@ -179,18 +180,21 @@ static void on_netinfo(struct most_interface *iface,
static int most_nd_open(struct net_device *dev)
{
struct net_dev_context *nd = netdev_priv(dev);
int ret = 0;
BUG_ON(!nd->tx.linked || !nd->rx.linked);
mutex_lock(&probe_disc_mt);
if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) {
netdev_err(dev, "most_start_channel() failed\n");
return -EBUSY;
ret = -EBUSY;
goto unlock;
}
if (most_start_channel(nd->iface, nd->tx.ch_id, &aim)) {
netdev_err(dev, "most_start_channel() failed\n");
most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
return -EBUSY;
ret = -EBUSY;
goto unlock;
}
netif_carrier_off(dev);
......@@ -201,7 +205,10 @@ static int most_nd_open(struct net_device *dev)
netif_wake_queue(dev);
if (nd->iface->request_netinfo)
nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, on_netinfo);
return 0;
unlock:
mutex_unlock(&probe_disc_mt);
return ret;
}
static int most_nd_stop(struct net_device *dev)
......@@ -289,6 +296,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
struct net_dev_channel *ch;
struct net_device *dev;
unsigned long flags;
int ret = 0;
if (!iface)
return -EINVAL;
......@@ -296,13 +304,15 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
if (ccfg->data_type != MOST_CH_ASYNC)
return -EINVAL;
mutex_lock(&probe_disc_mt);
nd = get_net_dev_context(iface);
if (!nd) {
dev = alloc_netdev(sizeof(struct net_dev_context), "meth%d",
NET_NAME_UNKNOWN, most_nd_setup);
if (!dev)
return -ENOMEM;
if (!dev) {
ret = -ENOMEM;
goto unlock;
}
nd = netdev_priv(dev);
nd->iface = iface;
......@@ -313,25 +323,26 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
spin_unlock_irqrestore(&list_lock, flags);
ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
ch->ch_id = channel_idx;
ch->linked = true;
} else {
ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
if (ch->linked) {
pr_err("direction is allocated\n");
return -EINVAL;
ret = -EINVAL;
goto unlock;
}
ch->ch_id = channel_idx;
ch->linked = true;
if (register_netdev(nd->dev)) {
pr_err("register_netdev() failed\n");
ch->linked = false;
return -EINVAL;
ret = -EINVAL;
goto unlock;
}
}
ch->ch_id = channel_idx;
ch->linked = true;
return 0;
unlock:
mutex_unlock(&probe_disc_mt);
return ret;
}
static int aim_disconnect_channel(struct most_interface *iface,
......@@ -340,17 +351,23 @@ static int aim_disconnect_channel(struct most_interface *iface,
struct net_dev_context *nd;
struct net_dev_channel *ch;
unsigned long flags;
int ret = 0;
mutex_lock(&probe_disc_mt);
nd = get_net_dev_context(iface);
if (!nd)
return -EINVAL;
if (!nd) {
ret = -EINVAL;
goto unlock;
}
if (nd->rx.linked && channel_idx == nd->rx.ch_id)
if (nd->rx.linked && channel_idx == nd->rx.ch_id) {
ch = &nd->rx;
else if (nd->tx.linked && channel_idx == nd->tx.ch_id)
} else if (nd->tx.linked && channel_idx == nd->tx.ch_id) {
ch = &nd->tx;
else
return -EINVAL;
} else {
ret = -EINVAL;
goto unlock;
}
if (nd->rx.linked && nd->tx.linked) {
/*
......@@ -367,7 +384,9 @@ static int aim_disconnect_channel(struct most_interface *iface,
free_netdev(nd->dev);
}
return 0;
unlock:
mutex_unlock(&probe_disc_mt);
return ret;
}
static int aim_resume_tx_channel(struct most_interface *iface,
......@@ -463,6 +482,7 @@ static struct most_aim aim = {
static int __init most_net_init(void)
{
spin_lock_init(&list_lock);
mutex_init(&probe_disc_mt);
return most_register_aim(&aim);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment