Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a75c0312 authored by Christian Gromm's avatar Christian Gromm Committed by Greg Kroah-Hartman
Browse files

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: 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 44858424
Loading
Loading
Loading
Loading
+15 −11
Original line number Diff line number Diff line
@@ -298,15 +298,16 @@ static struct net_dev_context *get_net_dev_context(
	struct most_interface *iface)
{
	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) {
		if (nd->iface == iface) {
			spin_unlock(&list_lock);
			spin_unlock_irqrestore(&list_lock, flags);
			return nd;
		}
	}
	spin_unlock(&list_lock);
	spin_unlock_irqrestore(&list_lock, flags);
	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_channel *ch;
	unsigned long flags;

	if (!iface)
		return -EINVAL;
@@ -332,9 +334,9 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,

		nd->iface = iface;

		spin_lock(&list_lock);
		spin_lock_irqsave(&list_lock, flags);
		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;
@@ -377,6 +379,7 @@ static int aim_disconnect_channel(struct most_interface *iface,
{
	struct net_dev_context *nd;
	struct net_dev_channel *ch;
	unsigned long flags;

	nd = get_net_dev_context(iface);
	if (!nd)
@@ -398,9 +401,9 @@ static int aim_disconnect_channel(struct most_interface *iface,
	most_net_rm_netdev_safe(nd);

	if (!nd->rx.linked && !nd->tx.linked) {
		spin_lock(&list_lock);
		spin_lock_irqsave(&list_lock, flags);
		list_del(&nd->list);
		spin_unlock(&list_lock);
		spin_unlock_irqrestore(&list_lock, flags);
		kfree(nd);
	}

@@ -514,20 +517,21 @@ static int __init most_net_init(void)
static void __exit most_net_exit(void)
{
	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_del(&nd->list);
		spin_unlock(&list_lock);
		spin_unlock_irqrestore(&list_lock, flags);
		/*
		 * do not call most_stop_channel() here, because channels are
		 * going to be closed in ndo_stop() after unregister_netdev()
		 */
		most_net_rm_netdev_safe(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);
	pr_info("most_net_exit()\n");