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

Commit 9996e424 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "net: usb: Using workqueue as bottom half handler"

parents ef529943 32781950
Loading
Loading
Loading
Loading
+33 −16
Original line number Diff line number Diff line
@@ -89,7 +89,8 @@ static u8 node_id [ETH_ALEN];

static const char driver_name [] = "usbnet";

struct workqueue_struct		*usbnet_wq;
static struct workqueue_struct	*usbnet_wq;

/* use ethtool to change the level for any given device */
static int msg_level = -1;
module_param (msg_level, int, 0);
@@ -403,7 +404,7 @@ unlock_and_schedule:
	if (skb_defer_rx_timestamp(skb))
		return;

	status = netif_rx (skb);
	status = netif_rx_ni(skb);
	if (status != NET_RX_SUCCESS)
		netif_dbg(dev, rx_err, dev->net,
			  "netif_rx status %d\n", status);
@@ -500,7 +501,7 @@ static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
	spin_lock(&dev->done.lock);
	__skb_queue_tail(&dev->done, skb);
	if (dev->done.qlen == 1)
		tasklet_schedule(&dev->bh);
		queue_work(usbnet_wq, &dev->bh_w);
	spin_unlock_irqrestore(&dev->done.lock, flags);
	return old_state;
}
@@ -579,7 +580,7 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
		default:
			netif_dbg(dev, rx_err, dev->net,
				  "rx submit, %d\n", retval);
			tasklet_schedule (&dev->bh);
			queue_work(usbnet_wq, &dev->bh_w);
			break;
		case 0:
			__usbnet_queue_skb(&dev->rxq, skb, rx_start);
@@ -745,7 +746,7 @@ void usbnet_resume_rx(struct usbnet *dev)
		num++;
	}

	tasklet_schedule(&dev->bh);
	queue_work(usbnet_wq, &dev->bh_w);

	netif_dbg(dev, rx_status, dev->net,
		  "paused rx queue disabled, %d skbs requeued\n", num);
@@ -814,7 +815,7 @@ void usbnet_unlink_rx_urbs(struct usbnet *dev)
{
	if (netif_running(dev->net)) {
		(void) unlink_urbs (dev, &dev->rxq);
		tasklet_schedule(&dev->bh);
		queue_work(usbnet_wq, &dev->bh_w);
	}
}
EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs);
@@ -887,7 +888,7 @@ int usbnet_stop (struct net_device *net)
	 */
	dev->flags = 0;
	del_timer_sync (&dev->delay);
	tasklet_kill (&dev->bh);
	cancel_work_sync(&dev->bh_w);
	if (!pm)
		usb_autopm_put_interface(dev->intf);

@@ -972,7 +973,7 @@ int usbnet_open (struct net_device *net)
	clear_bit(EVENT_RX_KILL, &dev->flags);

	// delay posting reads until we're fully open
	tasklet_schedule (&dev->bh);
	queue_work(usbnet_wq, &dev->bh_w);
	if (info->manage_power) {
		retval = info->manage_power(dev, 1);
		if (retval < 0) {
@@ -1114,7 +1115,7 @@ static void __handle_link_change(struct usbnet *dev)
		 */
	} else {
		/* submitting URBs for reading packets */
		tasklet_schedule(&dev->bh);
		queue_work(usbnet_wq, &dev->bh_w);
	}

	/* hard_mtu or rx_urb_size may change during link change */
@@ -1187,7 +1188,7 @@ fail_halt:
					   status);
		} else {
			clear_bit (EVENT_RX_HALT, &dev->flags);
			tasklet_schedule (&dev->bh);
			queue_work(usbnet_wq, &dev->bh_w);
		}
	}

@@ -1212,7 +1213,7 @@ fail_halt:
			usb_autopm_put_interface(dev->intf);
fail_lowmem:
			if (resched)
				tasklet_schedule (&dev->bh);
				queue_work(usbnet_wq, &dev->bh_w);
		}
	}

@@ -1308,13 +1309,14 @@ void usbnet_tx_timeout (struct net_device *net)
	struct usbnet		*dev = netdev_priv(net);

	unlink_urbs (dev, &dev->txq);
	tasklet_schedule (&dev->bh);
	queue_work(usbnet_wq, &dev->bh_w);
	/* this needs to be handled individually because the generic layer
	 * doesn't know what is sufficient and could not restore private
	 * information if a remedy of an unconditional reset were used.
	 */
	if (dev->driver_info->recover)
		(dev->driver_info->recover)(dev);

}
EXPORT_SYMBOL_GPL(usbnet_tx_timeout);

@@ -1572,13 +1574,21 @@ static void usbnet_bh (unsigned long param)
					  "rxqlen %d --> %d\n",
					  temp, dev->rxq.qlen);
			if (dev->rxq.qlen < RX_QLEN(dev))
				tasklet_schedule (&dev->bh);
				queue_work(usbnet_wq, &dev->bh_w);
		}
		if (!enable_ipa_bridge && dev->txq.qlen < TX_QLEN(dev))
			netif_wake_queue (dev->net);
	}
}

static void usbnet_bh_w(struct work_struct *work)
{
	struct usbnet		*dev =
		container_of(work, struct usbnet, bh_w);
	unsigned long param = (unsigned long)dev;

	usbnet_bh(param);
}

/*-------------------------------------------------------------------------
 *
@@ -2065,8 +2075,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
	skb_queue_head_init (&dev->txq);
	skb_queue_head_init (&dev->done);
	skb_queue_head_init(&dev->rxq_pause);
	dev->bh.func = usbnet_bh;
	dev->bh.data = (unsigned long) dev;
	INIT_WORK(&dev->bh_w, usbnet_bh_w);
	INIT_WORK (&dev->kevent, kevent);
	init_usb_anchor(&dev->deferred);
	dev->delay.function = usbnet_bh;
@@ -2347,7 +2356,7 @@ int usbnet_resume (struct usb_interface *intf)

			if (!(dev->txq.qlen >= TX_QLEN(dev)))
				netif_tx_wake_all_queues(dev->net);
			tasklet_schedule (&dev->bh);
			queue_work(usbnet_wq, &dev->bh_w);
		}
	}

@@ -2599,12 +2608,20 @@ static int __init usbnet_init(void)
		FIELD_SIZEOF(struct sk_buff, cb) < sizeof(struct skb_data));

	eth_random_addr(node_id);

	usbnet_wq  = create_singlethread_workqueue("usbnet");
	if (!usbnet_wq) {
		pr_err("%s: Unable to create workqueue:usbnet\n", __func__);
		return -ENOMEM;
	}

	return 0;
}
module_init(usbnet_init);

static void __exit usbnet_exit(void)
{
	destroy_workqueue(usbnet_wq);
}
module_exit(usbnet_exit);

+1 −1
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ struct usbnet {
	unsigned		interrupt_count;
	struct mutex		interrupt_mutex;
	struct usb_anchor	deferred;
	struct tasklet_struct	bh;
	struct work_struct	bh_w;

	struct work_struct	kevent;
	unsigned long		flags;