staging: most: aim-network: fix interrupt unsafe spinlocks

The networking AIM does not use the *_irqsave and *_irqrestore flavored
spinlock functions. The rx_completion callback, however, can be called
from an interrupt context.

This patch is needed to fix this problem.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Christian Gromm 2016-08-18 15:28:27 +02:00 committed by Greg Kroah-Hartman
parent 4485842493
commit a75c03126f

View File

@ -298,15 +298,16 @@ static struct net_dev_context *get_net_dev_context(
struct most_interface *iface) struct most_interface *iface)
{ {
struct net_dev_context *nd, *tmp; struct net_dev_context *nd, *tmp;
unsigned long flags;
spin_lock(&list_lock); spin_lock_irqsave(&list_lock, flags);
list_for_each_entry_safe(nd, tmp, &net_devices, list) { list_for_each_entry_safe(nd, tmp, &net_devices, list) {
if (nd->iface == iface) { if (nd->iface == iface) {
spin_unlock(&list_lock); spin_unlock_irqrestore(&list_lock, flags);
return nd; return nd;
} }
} }
spin_unlock(&list_lock); spin_unlock_irqrestore(&list_lock, flags);
return NULL; return NULL;
} }
@ -316,6 +317,7 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
{ {
struct net_dev_context *nd; struct net_dev_context *nd;
struct net_dev_channel *ch; struct net_dev_channel *ch;
unsigned long flags;
if (!iface) if (!iface)
return -EINVAL; return -EINVAL;
@ -332,9 +334,9 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
nd->iface = iface; nd->iface = iface;
spin_lock(&list_lock); spin_lock_irqsave(&list_lock, flags);
list_add(&nd->list, &net_devices); list_add(&nd->list, &net_devices);
spin_unlock(&list_lock); spin_unlock_irqrestore(&list_lock, flags);
} }
ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx; ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
@ -377,6 +379,7 @@ static int aim_disconnect_channel(struct most_interface *iface,
{ {
struct net_dev_context *nd; struct net_dev_context *nd;
struct net_dev_channel *ch; struct net_dev_channel *ch;
unsigned long flags;
nd = get_net_dev_context(iface); nd = get_net_dev_context(iface);
if (!nd) if (!nd)
@ -398,9 +401,9 @@ static int aim_disconnect_channel(struct most_interface *iface,
most_net_rm_netdev_safe(nd); most_net_rm_netdev_safe(nd);
if (!nd->rx.linked && !nd->tx.linked) { if (!nd->rx.linked && !nd->tx.linked) {
spin_lock(&list_lock); spin_lock_irqsave(&list_lock, flags);
list_del(&nd->list); list_del(&nd->list);
spin_unlock(&list_lock); spin_unlock_irqrestore(&list_lock, flags);
kfree(nd); kfree(nd);
} }
@ -514,20 +517,21 @@ static int __init most_net_init(void)
static void __exit most_net_exit(void) static void __exit most_net_exit(void)
{ {
struct net_dev_context *nd, *tmp; struct net_dev_context *nd, *tmp;
unsigned long flags;
spin_lock(&list_lock); spin_lock_irqsave(&list_lock, flags);
list_for_each_entry_safe(nd, tmp, &net_devices, list) { list_for_each_entry_safe(nd, tmp, &net_devices, list) {
list_del(&nd->list); list_del(&nd->list);
spin_unlock(&list_lock); spin_unlock_irqrestore(&list_lock, flags);
/* /*
* do not call most_stop_channel() here, because channels are * do not call most_stop_channel() here, because channels are
* going to be closed in ndo_stop() after unregister_netdev() * going to be closed in ndo_stop() after unregister_netdev()
*/ */
most_net_rm_netdev_safe(nd); most_net_rm_netdev_safe(nd);
kfree(nd); kfree(nd);
spin_lock(&list_lock); spin_lock_irqsave(&list_lock, flags);
} }
spin_unlock(&list_lock); spin_unlock_irqrestore(&list_lock, flags);
most_deregister_aim(&aim); most_deregister_aim(&aim);
pr_info("most_net_exit()\n"); pr_info("most_net_exit()\n");