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

Commit f742aa8a authored by Alexey Orishko's avatar Alexey Orishko Committed by David S. Miller
Browse files

USB CDC NCM: tx_fixup() race condition fix



- tx_fixup() can be called from either timer callback or from xmit()
  in usbnet, so spinlock is added to avoid concurrency-related problem.
- minor correction due to checkpatch warning for some line over 80
  chars after previous patch was applied.

Signed-off-by: default avatarAlexey Orishko <alexey.orishko@stericsson.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1956cc52
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@
#include <linux/usb/usbnet.h>
#include <linux/usb/cdc.h>

#define	DRIVER_VERSION				"30-Nov-2010"
#define	DRIVER_VERSION				"17-Jan-2011"

/* CDC NCM subclass 3.2.1 */
#define USB_CDC_NCM_NDP16_LENGTH_MIN		0x10
@@ -868,16 +868,20 @@ static void cdc_ncm_tx_timeout(unsigned long arg)
	if (ctx->tx_timer_pending != 0) {
		ctx->tx_timer_pending--;
		restart = 1;
	} else
	} else {
		restart = 0;
	}

	spin_unlock(&ctx->mtx);

	if (restart)
	if (restart) {
		spin_lock(&ctx->mtx);
		cdc_ncm_tx_timeout_start(ctx);
	else if (ctx->netdev != NULL)
		spin_unlock(&ctx->mtx);
	} else if (ctx->netdev != NULL) {
		usbnet_start_xmit(NULL, ctx->netdev);
	}
}

static struct sk_buff *
cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
@@ -900,7 +904,6 @@ cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
	skb_out = cdc_ncm_fill_tx_frame(ctx, skb);
	if (ctx->tx_curr_skb != NULL)
		need_timer = 1;
	spin_unlock(&ctx->mtx);

	/* Start timer, if there is a remaining skb */
	if (need_timer)
@@ -908,6 +911,8 @@ cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)

	if (skb_out)
		dev->net->stats.tx_packets += ctx->tx_curr_frame_num;

	spin_unlock(&ctx->mtx);
	return skb_out;

error: